Source
[521521] adaptation
This question is the same as the monotonic incrementing subsequence question mentioned above. However, if the data volume of this question is large, the previous method will time out, the previous method DP [I]: used to store the length of the longest incremental sub-sequence ending with AI; the time complexity is O (n2 ), the data range of this question is 100000, and this method will time out;
Therefore, we adopt another method, using DP [I]: to store the minimum value of the end element in an incremental sequence with an I + 1 length;
Create a one-dimensional array DP [], use DP [I] To save the value of the end element of the monotonic subsequence with the length of I, and use top to save the maximum length of the monotonic subsequence.
Initial Top = 1, DP [1] = A1;
Then, we traverse the sequence an (I: 2 ~ N ). Obviously, we will encounter two situations:
1. A [I]> DP [Top]. In this case, we add a [I] to the monotonic sequence with the top length. The sequence length is top + 1, and the top value is also updated, that is, DP [++ top] = A [I];
2. A [I] <= DP [Top]. In this case, a [I] cannot add a monotonic sequence with the top length. How many sequences should it add?
The method is to traverse DP [] (J: top-1 ~ 1) until the condition a [I]> DP [J] is met, in this case, similar to step 1, we can add a [I] to the monotonic sequence with a length of J, at this time, the sequence length is J + 1; (This section is reproduced in the http://www.cnblogs.com/mycapple/archive/2012/08/22/2651453.html)
If we do this directly, the time complexity will reach O (n2), but here we can optimize it. We can adopt a more efficient method when traversing updates; here we can use binary search to update the previous A [I]. The time complexity of this method is O (nlogn)
The following code is used:
# Include <cstdio> # include <cstring> const int maxn = 100001; int DP [maxn], a [maxn]; int binary_search (INT Len, int K) // Binary Search {// search for an int start, end, mid; Start = 1; end = Len; which is smaller than or equal to the first DP [I; while (start <= END) {mid = (start + end)> 1; if (k = DP [Mid]) return mid; if (k> DP [Mid]) Start = Mid + 1; else end = mid-1;} return start;} int main () {int N, I, T, len; while (scanf ("% d", & N )! = EOF) {memset (DP, 0, sizeof (DP); for (I = 0; I <n; I ++) scanf ("% d ", & A [I]); Len = 1; DP [1] = A [0]; // start from 1 for (I = 1; I <N; I ++) {T = binary_search (Len, a [I]); // query the location where a [I] is to be inserted through the binary search DP [T] = A [I]; // update the Dp value if (T> Len) // If the inserted position is at the end, update the maximum length Len = T;} printf ("% d \ n", Len );}}
The following is the optimal code, which is short: A lower_bound function in STL is used. This function is a binary search and returns the first location smaller than Val, it will be more convenient to use this function, and there is a upper_bound function; http://blog.csdn.net/niushuai666/article/details/6734403 content can refer to this blog
#include<cstdio>#include<algorithm>using namespace std;const int MAX=100100;int num[MAX],top=0;int main(){int n;while(~scanf("%d",&n)){scanf("%d",&num[0]);top=1;for(int i=1;i!=n;i++){scanf("%d",&num[i]);int * p=lower_bound(num,num+top,num[i]);if(p-num==top) ++top;*p=num[i];}printf("%d\n",top);}}