先是nlogn的LIS解法
/* LIS nlogn解法 */ #include<iostream> #include<cstring> #include<cstdio> using namespace std; //结尾的数字越小,说明相同长度下当前序列越优 int lis[100005],a[100005];//lis[i]表示长度为i的最优的结尾数 int n,len=0; int find(int x){//找到lis中第一个大于等于x的数的下标 int l=0,r=len; while(l<r){ int mid=l+r>>1; if(lis[mid]>=x) r=mid; else l=mid+1; } return l; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); lis[1]=a[1];len++; for(int i=2;i<=n;i++){//按顺序处理每一个数 if(a[i]>lis[len])//可以更新新长度了 lis[++len]=a[i]; else{//对于一个a[i],可以更新以它为结尾的最长lis的结尾 int pos=find(a[i]);//找到lis中第一个大于等于a[i]的数,pos也是以那个数结尾的长度 lis[pos]=a[i]; //把那个数替换了 } } printf("%d\n",len); return 0; }
线段树解LIS