LIS最长上升子序列

http://cogs.pro/cogs/problem/problem.php?pid=1398

设 A[t]表示序列中的第t个数,F[t]表示从1到t这一段中以t结尾的最长上升子序列的长度

根据F[]的值进行分类。对于F[]的每一个取值k,我们只需要保留满足F[t] = k的所有A[t]中的最小值。设D[k]记录这个值,即D[k] = min{A[t]} (F[t] = k)。 


注意到D[]的两个特点: 
(1) D[k]的值是在整个计算过程中是单调不下降的。 
(2) D[]的值是有序的,即D[1] < D[2] < D[3] < ... < D[n]。 

每次二分一个小于a[t]的最大的D[i],因为D[i+1]>a[t]且F[t]为i+1,所以D[i+1]=a[t]

#include<cstdio>
int d[1050],a[1050]={-1324756};
int main(){
    freopen("lis1.in","r",stdin);
    freopen("lis1.out","w",stdout);
    int i,n,cnt=0,r,l,mid;scanf("%d",&n);
    for(i=0;i<n;i++){
        scanf("%d",a+i);
        l=1;r=cnt;
        while(l<=r){
            mid=(l+r)>>1;
            if(d[mid]<a[i])l=mid+1;
            else r=mid-1;
        }
        d[l]=a[i];
        if(l>cnt)cnt=l;
    }
    printf("%d",cnt);
    return 0;
}

 

posted @ 2017-03-11 10:55  Bennettz  阅读(136)  评论(0编辑  收藏  举报