樹狀數組求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;
}

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