二分查找在最长不下降子序列中的应用

来源:互联网 发布:淘宝复核认证本人不在 编辑:程序博客网 时间:2024/05/22 15:55
最长不下降子序列问题:问题:给你一个长度为n的整数序列,按从左往右的顺序选择尽量多的数字并且满足这些数字不下降。朴素dp算法:F[i]表示到第i位为止的最长不下降子序列长度F[i]=max(F[j])+1,其中(j<i且a[j]<=a[i])时间复杂度:O(n2)考虑维护一个队列g,用g[i]表示长度为i的最长不下降子序列结尾的最小值。根据g[i]的单调性,可以用二分查找的方法快速找到以当前数a[i]结尾的最长不下降子序列长度。
#include<cstdio>#include<cstring>#define FA(i,s,t) for(int i=s;i<=t;i++)#define FD(i,s,t) for(int i=s;i>=t;i--)using namespace std;int n;int num[10000];int g[10000],f[10000];void Insert(int x,int s,int t) //不使用递归的方法提高效率{    int left,right,mid;    left=s;    right=t;    while(left<=right)    {        mid=(left+right)/2;        if(g[mid]==x)        {            while(g[mid]==x) ++mid;            g[mid]=x;            return;        }        if(g[mid]>x) right=mid-1;        if(g[mid]<x)        {            if(g[mid+1]>x)            {                g[mid+1]=x;                return;            }            left=mid+1;        }    }}int main(){    scanf("%d",&n);    FA(i,1,n)    {        scanf("%d",&num[i]);    }    memset(g,0,sizeof(g));    int t=1;    FA(i,1,n)    {        if(num[i]>=g[t-1])        {            g[t]=num[i];            t++;        }        else        {            Insert(num[i],0,t);        }    }    int ans=t-1;    printf("%d\n",ans);    return 0;}
0 0