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;
}