(NYoj 214)单调递增子序列(二) --非递归思想模板

来源:互联网 发布:淘宝代办签证靠谱吗 编辑:程序博客网 时间:2024/06/14 06:45

单调递增子序列(二)
时间限制:1000 ms | 内存限制:65535 KB
难度:4
描述
给定一整型数列{a1,a2…,an}(0< n<=100000),找出单调递增最长子序列,并求出其长度。

如:1 9 10 5 11 2 13的最长单调递增子序列是1 9 10 11 13,长度为5。

输入
有多组测试数据(<=7)
每组测试数据的第一行是一个整数n表示序列中共有n个整数,随后的下一行里有n个整数,表示数列中的所有元素.每个整形数中间用空格间隔开(0< n<=100000)。
数据以EOF结束 。
输入数据保证合法(全为int型整数)!
输出
对于每组测试数据输出整形数列的最长递增子序列的长度,每个输出占一行。
样例输入
7
1 9 10 5 11 2 13
2
2 -1
样例输出
5
1
来源
[521521]改编
上传者
ACM_赵铭浩

分析:
如果接下来一个数比已经找到的最大子序列的最后一个值大,则将其添加在序列后面。否则在已找到的子序列中找到第一个比他大的数,将这个数替换掉,使找到的子序列”潜力”最大。

AC代码:

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>using namespace std;const int N = 100010;int a[N];int ans[N];int d;int find(int a,int b,int x){    if(a==b) return a;    int m = (a+b)/2;    if(ans[m]<=x) return find(m+1,b,x);    else return find(a,m,x);}int main(){    int n;    while(scanf("%d",&n)!=EOF)    {        for(int i=0;i<n;i++)            scanf("%d",&a[i]);        d=0;        ans[d++]=a[0];        for(int i=1;i<n;i++)        {            if(a[i]>ans[d-1]) ans[d++]=a[i];            else ans[find(0,d-1,a[i])]=a[i];        }        printf("%d\n",d);    }    return 0;}
1 0
原创粉丝点击