832. Increasing
subsequence
Given n integers x1, x2, ..., xn. Delete from them the least number of integers so
that the rest were in ascending order.
Input. The first line contains the number n (1 ≤ n ≤ 105).
The second line contains the integers x1, x2, ..., xn (1 ≤ xi ≤
60 000).
Output. Print in the first line the number
of not erased integers. In the second line print the list of unerased integers
in the original order. If several answers exist, print any.
Sample
input |
Sample
output |
6 2 5 3 4 6 1 |
4 2 3 4 6 |
longest increasing
subsequence
The largest increasing subsequence must be found and printed.
For each element xi (1 ≤ i ≤ n), find the length of the LIS that
ends at xi. Store these values in array L. This information is enough to find the LIS
itself in linear time. The length of the LIS equals to the
maximum number k in array L. Let this largest
number k be in the index pos.
Then the LIS ends with the number xpos. Decrease pos
until L[pos] becomes equal to k – 1. The current xpos will be the penultimate element in the LIS. And
so on, we continue to move the pos index to the start of
array L, stopping at the first positions for which L[pos] = k – 2, …, L[pos] =
0.
Theorem. Consider the indices i1 < i2 < …< im,
for which L[i1] = L[i2] = …= L[im]. Then the sequence xi1, xi2, …, xim is decreasing.
Example
The solitaire layout looks like:
Declare the arrays.
#define MAX 60001
int x[MAX], lis[MAX], L[MAX];
Print the LIS.
void PrintSeq(int
pos)
{
if (size <
0) return;
while(L[pos]
!= size) pos--;
size--; PrintSeq(pos-1);
printf("%d
",x[pos]);
}
The main part of the program. Read the input sequence.
scanf("%d",&n);
for(i = 0; i < n; i++)
scanf("%d",&x[i]);
Fill the arrays.
for (len = i = 0; i < n; i++)
{
pos = lower_bound(lis,lis+len,x[i]) - lis;
lis[pos] = x[i];
L[i] = pos;
if (pos ==
len) len++;
}
Print the largest increasing subsequence.
printf("%d\n",len); size = len - 1;
PrintSeq(n-1);
printf("\n");