codevs3955最长严格上升子序列

 时间限制: 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\n",i-1);
            return 0;
        }
    }
    return 0;
}

 

posted @ 2017-07-17 22:09  ANhour  阅读(179)  评论(0)    收藏  举报