树状数组求LIS

树状数组求LIS

优点:

同样是O(nlogn)的复杂度
二分做法只能计算出当前序列的LIS
而树状数组可以计算出以每一个a(i)为结尾的LIS

且二分的做法只能计算出答案,无法得到具体方案。

做法:

树状数组维护前缀max

设以a(i)结尾的LIS为F(i)
树状数组的c(x)存放以x为结尾的LIS,注意这里的x是一个具体的值,而不是下标,即c(a(i))=F(i)
每次插入一个新的数a(i)的时候,F(i)=ask(a(i))+1,然后插入,add(a(i),F(i))

原理是树状数组的查询ask(a(i))可以O(logn)计算出前i-1个数中小于a(i)中的F(i)的最大值。

另外:c(i)代表以a(i)为结尾的LIS,数组c的大小取决于a(i)的最大值,当数据范围大的时候需要先离散化


AtCoder2827 LIS

题意:

给长度为n的数组,计算LIS。
数据范围:n<=1e5

code:

#include<bits/stdc++.h>
using namespace std;
const int maxm=1e5+5;
int c[maxm];
int f[maxm];
int a[maxm];
int lowbit(int i){
    return i&-i;
}
void add(int i,int t){
    while(i<maxm){
        c[i]=max(c[i],t);
        i+=lowbit(i);
    }
}
int ask(int i){
    int ans=0;
    while(i){
        ans=max(ans,c[i]);
        i-=lowbit(i);
    }
    return ans;
}
signed main(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    for(int i=1;i<=n;i++){
        f[i]=ask(a[i])+1;
        add(a[i],f[i]);
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        ans=max(ans,f[i]);
    }
    cout<<ans<<endl;
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章