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; }