5 9 4 1 3 7 6 7
那么栈的变化过程为:
5
5 9
4 9 //用4更新了5
1 9
1 3
1 3 7
1 3 6
1 3 6 7
最后的结果,最长递增子序列的长度就是栈的大小,这里是4。要注意的是最后栈里的元素并不就一定是所求的序列,例如如果输入
2 5 1
那么最后得到的栈应该是
1 5
而实际上要求的序列是
2 5
至于要怎么求这个序列。。。这个。。。看了讲解之后自己还是没研究透彻。。。哈哈,有空再说了。算法的正确性没有经过严格的证明,不过想想看应该是对的吧,哈哈,偷懒了。
代码(写得有些丑陋的):
/*
习题 33:最长递增子序列★★★
问题描述:
所谓子序列,就是在原序列里删掉若干个元素后剩下的序列,以字符串"abcdefg"为例子,去掉bde得到子序列"acfg"
现在的问题是,给你一个数字序列,你要求出它最长的单调递增子序列。
输入:
多组测试数据,每组测试数据第一行是n(1<=n<=10000),下一行是n个比1e9小的非负整数
输出:
对于每组测试数据输出一行,每行内容是最长的单调递增子序列的长度
样例输入:
5
1 2 4 8 16
5
1 10 4 9 7
9
0 0 0 1 1 1 5 5 5
样例输出:
5
3
3
难度:normal
*/
#include <cstdio> #define MAXN 10000 long long stack[MAXN]; int n; long long t; int top; int main() { int i; int mid,high,low; while(scanf("%d",&n)==1 && n!=0) { scanf("%lld",&stack[0]); top=1; for(i=1;i<n;i++) { scanf("%lld",&t); if(t>stack[top-1]) //一 stack[top++]=t; if(t==stack[top-1]) //二 continue; else //三 { low=0; high=top-1; while(true) { mid=(low+high)/2; if(stack[mid]>=t && (mid==0 || stack[mid-1]<t)) { stack[mid]=t; break; } if(stack[mid]<t) low=mid+1; else high=mid-1; } } } printf("%d\n",top); } return 0; }