时间限制: 1 s
空间限制: 256000 KB
题目等级 : 钻石 Diamond
题目描述 Description
给一个数组a1, a2 ... an,找到最长的上升降子序列ab1<ab2< .. <abk,其中b1<b2<..bk。
输出长度即可。
输入描述 Input Description
第一行,一个整数N。
第二行 ,N个整数(N < = 1000000)
输出描述 Output Description
输出K的极大值,即最长不下降子序列的长度
样例输入 Sample Input
5
9 3 6 2 7
样例输出 Sample Output
3
数据范围及提示 Data Size & Hint
n<=1000000
为了方便大家调试,数据名称已被修改——THREE
【思路】
n^2算法一定超时。
考虑....nlogn的算法。
dp[i]表示长度为i的上升序列的最后一个最小的数。
重点是最小的。只有最小才能扩展更多的数。
比如
2
4
3
1
图复制不上....1 2 3 4 表示序号,高度表示这个序号代表的数的大小,越高越大。
发现1 2 上升序列长度为2, 3 4序列长度也为2 那么dp[2] 是2还是4呢,(2,4表示是序号啊)
应该是4,因为4比2小 能扩展加入的数更多。
【code】
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=0x3f3f3f3f; int n,a[1000009],dp[1000009]; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); memset(dp,0x3f,sizeof(dp)); for(int i=1;i<=n;i++) { int p=upper_bound(dp+1,dp+n+1,a[i])-dp; if(a[i]!=dp[p-1])//严格上升序列 dp[p]=a[i]; } for(int i=1;i<=n+1;i++) { if(dp[i]==maxn) { printf("%d ",i-1); return 0; } } return 0; }