【noiOJ】p1759
1759:最长上升子序列
- 总时间限制:
- 2000ms
- 内存限制:
- 65536kB
- 描述
- 一个数的序列bi,当b1 < b2 < ... < bS的时候,我们称这个序列是上升的。对于给定的一个序列(a1, a2, ..., aN),我们可以得到一些上升的子序列(ai1, ai2, ..., aiK),这里1 <= i1 < i2 < ... < iK <= N。比如,对于序列(1, 7, 3, 5, 9, 4, 8),有它的一些上升子序列,如(1, 7), (3, 4, 8)等等。这些子序列中最长的长度是4,比如子序列(1, 3, 5, 8).
你的任务,就是对于给定的序列,求出最长上升子序列的长度。 - 输入
- 输入的第一行是序列的长度N (1 <= N <= 1000)。第二行给出序列中的N个整数,这些整数的取值范围都在0到10000。
- 输出
- 最长上升子序列的长度。
- 样例输入
-
7 1 7 3 5 9 4 8
- 样例输出
-
4
- 来源
- 翻译自 Northeastern Europe 2002, Far-Eastern Subregion 的比赛试题
- source:最长上升子序列nlogn:数组b保存的是长度为len的最长上升子序列的第len个数,要使第len个数最小,不断更新b数组,找到最优的最长上升子序列。
- 若找到比第len个数大的,更新len。
-
1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 int len,n; 5 int a[1000000+10],b[1000000+10]; 6 int dfen(int x) 7 { 8 int left=0,right=len,mid; 9 while (right-left>0) 10 { 11 mid=(right+left)/2; 12 if (b[mid]==a[x]) 13 return 0; 14 if (b[mid]<a[x]) 15 left=mid+1; 16 else 17 right=mid; 18 } 19 if (b[left]>a[x]) 20 return left; 21 else 22 return 0; 23 } 24 int main() 25 { 26 int i; 27 scanf("%d",&n); 28 for (i=1;i<=n;i++) 29 scanf("%d",&a[i]); 30 b[1]=a[1]; 31 len=1; 32 for (i=2;i<=n;i++) 33 if (a[i]>b[len]) 34 b[++len]=a[i]; 35 else 36 { 37 int pos; 38 pos=dfen(i); 39 if (pos!=0) 40 b[pos]=a[i]; 41 } 42 cout<<len; 43 return 0; 44 }
—Anime Otaku Save The World.