(Optional) Longest Increasing Subsequence
Authors: Michael Cao, Benjamin Qi, Andi Qu, Andrew Wang
Prerequisites
Finding and using the LIS of an array
Resources | |||
---|---|---|---|
cp-algo | A comprehensive guide (covers almost everything here) |
Focus Problem – read through this problem before continuing!
Tutorial
In this tutorial, let be the array we want to find the LIS for.
Resources | |||
---|---|---|---|
CPH | slow solution |
Let be the length of the longest increasing subsequence that ends on . We can then naively compute (and thus the LIS) in time:
C++
int find_lis(vector<int> a) {int n = a.size(), lis = 0;vector<int> dp(n, 1);for (int i = 0; i < n; i++) {for (int j = 0; j < i; j++)if (a[j] < a[i])dp[i] = max(dp[i], dp[j] + 1);lis = max(lis, dp[i]);}return lis;
Java
public static int find_lis(int[] a) {int n = a.length, lis = 0;int[] dp = new int[n]; Arrays.fill(dp, 1);for (int i = 0; i < n; i++) {for (int j = 0; j < i; j++)if (a[j] < a[i])dp[i] = Math.max(dp[i], dp[j] + 1);lis = Math.max(lis, dp[i]);}return lis;
We can do much better than this though!
Let be an array where is the smallest element from the first elements of with an increasing sequence of length ending on it (or if there is no such element).
Lemma 1: forms a non-decreasing sequence.
Proof: Assume for a contradiction that for some , we have . However, this is impossible because an increasing sequence of length ending on some element implies that there is also an increasing sequence of length ending on that same sequence.
Lemma 2: The length of the LIS ending on is equal to the least index such that .
Proof: Firstly, since , there is an increasing sequence of length ending on . By Lemma 1, is non-decreasing, so for all . This means that the length of the LIS is .
Lemma 3: Exactly 1 element differs between and .
Proof: Obviously, we need to set to be since . We don't update anything else though, since for all and there are no increasing sequences ending on of length greater than .
To find and update the described in time, we can use a std::vector
and std::lower_bound
(or just a std::set
).
C++
int find_lis(vector<int> a) {vector<int> dp;for (int i : a) {int pos = lower_bound(dp.begin(), dp.end(), i) - dp.begin();if (pos == dp.size()) dp.push_back(i);else dp[pos] = i;}return dp.size();}
Java
public static int find_lis(int[] a) {ArrayList<Integer> dp = new ArrayList<Integer>();for (int i : a) {int pos = Collections.binarySearch(dp, i);if(pos < 0) pos = Math.abs(pos + 1);if (pos == dp.size()) dp.add(i);else dp.set(pos, i);}return dp.size();}
Application 1 - Non-intersecting Segments
Focus Problem – read through this problem before continuing!
This problem asks us to find the minimum number of disjoint sets of non-intersecting segments.
This seems quite intimidating, so let's break it up into two parts:
- Finding a set of non-intersecting segments
- Minimizing the number of these sets
First, what can we say about two segments and if they intersect (assuming )?
Since these segments are straight, notice how .
This means that a set of non-intersecting segments satisfies for all pairs !
Let be an array where means that the segment with its right endpoint at position has its left endpoint at position .
If we were asked to find the maximum size of a set of non-intersecting segments, the answer would be the LIS of !
Application 2 - Minimum Number of Increasing Sequences
Continuing from application 1, we now want to find the minimum number of increasing subsequences of .
Luckily for us, there's a simple solution to this - the minimum number of increasing subsequences of is simply the size of the LDS (longest decreasing subsequence) of !
(Try to prove this fact yourself - as a hint, assume the contrary for a contradiction.)
Code for PCB
C++
#include <bits/stdc++.h>using namespace std;int lis = 0;pair<int, int> a[100000];set<int> s;int main() {iostream::sync_with_stdio(false);cin.tie(0);
Java
import java.io.*;import java.util.*;class PCB{public static int find_lis(int[] a) {ArrayList<Integer> dp = new ArrayList<Integer>();for (int i : a) {int pos = Math.abs(Collections.binarySearch(dp, i));if (pos > dp.size()) dp.add(i);else dp.set(pos-1, i);
Application 3 - Number of LISes
Focus Problem – read through this problem before continuing!
This section is not complete.
#include <bits/stdc++.h>using namespace std;const int MOD = 30013;struct Trapezoid {int x1, x2, y1, y2;} traps[100001];int n, top[200001], bottom[200001];
Problems
Status | Source | Problem Name | Difficulty | Tags | Solution |
---|---|---|---|---|---|
Old Gold | Easy | Show TagsDP | External Sol | ||
LMiO | Easy | Show TagsDP | View Solution | ||
Baltic OI | Normal | Show TagsDP, Geometry | Show Sketch | ||
CEOI | Normal | Show TagsDP | |||
COCI | Hard | Show TagsDP, BIT | View Solution | ||
JOI | Very Hard | Show TagsDP | View Solution | ||
Plat | Insane | Show TagsDP | External Sol |