线段树解LIS

先是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

猜你喜欢

转载自www.cnblogs.com/zsben991126/p/9893286.html
今日推荐