最长非递减子序列(dp+二分)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_41061455/article/details/82217965

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述 

一只青蛙出去旅游,因为中国有一句古话说的好:“由简入奢易,由奢入俭难”,所以这只青蛙当看的当前景点比前面看过的景点差的时候,青蛙就会说“不开心”为了避免这只青蛙说“不开心”,并且使青蛙看的景点尽量的多,所以他请你帮忙给他安排一条线路,使青蛙可以看到尽量多的景点,并且不走回头路。

输入描述:

第一行为一个整数n,表示景点的数量
接下来n行,每行1个整数,分别表示第i个景点的质量

输出描述:

一个整数,表示青蛙最多可以看到几个景点

示例1

输入

10
3
18
7
14
10
12
23
30
16
24

输出

6

备注:

景点质量为1到n+23的整数
10<=n<23 10%

23<=n<233 30%

233<=n<2333 60%

2333<=n<23333 100%

题目要求最长非递减子序列,方法是dp+二分,dp[i]表示长度为i的最小尾元素.

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5;
int dp[maxn],a[maxn];
int Search(int len,int x)
{
    int l=0,r=len-1;
    while(l<=r)
    {
        int mid=(l+r)/2;
        if(x>=dp[mid-1]&&x<dp[mid]) return mid;
        else if(x<dp[mid-1]) r=mid-1;
        else l=mid+1;
    }
    return l;
}
int main()
{
    int n;
    while(scanf("%d",&n)==1)
    {
        scanf("%d",&a[0]);
        dp[0]=a[0];
        int len=1,j;
        for(int i=1;i<n;i++)
        {
            scanf("%d",&a[i]);
            if(a[i]<dp[0]) j=0;
            else if(a[i]>=dp[len-1]) j=len++;
            else j=Search(len,a[i]);
            dp[j]=a[i];
        }
        printf("%d\n",len);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_41061455/article/details/82217965