1. 程式人生 > >用樹狀數組實現的平衡樹

用樹狀數組實現的平衡樹

前綴和 ret pac 題目 con 前驅 ble -- val

一、題目:

洛谷模板

二、思路:

用樹狀數組實現的平衡樹,實現起來很簡單,但有很多細節需要考慮。

維護一個權值樹狀數組,查排名時直接前綴和,前驅、後繼都很簡單。比較難的是已知排名求值,需要倍增。

怎麽能寫二分呢?倍增比二分快幾百倍。——LSH

需要離散化,而細節很多,具體看代碼。

三、代碼:

#include<iostream>
#include<cstdio>
#include<algorithm>

using namespace std;
inline int read(void){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return f*x;
}

const int maxn=100005;

int n,b[maxn],cnt;

struct Opt{
    int opt,x;
}q[maxn];

struct BIT{
    int tree[maxn];
    inline int lowbit(int x){return x&(-x);}
    inline void add(int p,int x){
        while(p<=cnt){
            tree[p]+=x;
            p+=lowbit(p);
        }
    }
    inline int rank(int p){
        int ans=1;--p;
        while(p>0){
            ans+=tree[p];
            p-=lowbit(p);
        }
        return ans;
    }
    
    inline int val(int rank){
        int ans=0,Cnt=0;
        for(register int i=20;i>=0;--i){
            ans+=(1<<i);
            if(ans>cnt||Cnt+tree[ans]>=rank)ans-=(1<<i);
            else Cnt+=tree[ans];
        }
        return ++ans;
    }
    inline int pre(int x){
        return val(rank(x)-1);
    }
    inline int nxt(int x){
        return val(rank(x+1));
    }
}T;

int main(){
    n=read();
    for(register int i=1;i<=n;++i){
        q[i].opt=read();
        q[i].x=read();
        if(q[i].opt!=4)b[++cnt]=q[i].x;
    }
    sort(b+1,b+cnt+1);
    cnt=unique(b+1,b+cnt+1)-b-1;
    for(register int i=1;i<=n;++i){
        if(q[i].opt!=4)q[i].x=lower_bound(b+1,b+cnt+1,q[i].x)-b;
    }
    for(register int i=1;i<=n;++i){
        switch(q[i].opt){
            case 1:
                T.add(q[i].x,1);
                break;
            case 2:
                T.add(q[i].x,-1);
                break;
            case 3:
                cout<<T.rank(q[i].x)<<endl;
                break;
            case 4:
                // T.add(q[i].x,1);
                cout<<b[T.val(q[i].x)]<<endl;
                // T.add(q[i].x,-1);
                break;
            case 5:
                T.add(q[i].x,1);
                cout<<b[T.pre(q[i].x)]<<endl;
                T.add(q[i].x,-1);
                break;
            case 6:
                T.add(q[i].x,1);
                cout<<b[T.nxt(q[i].x)]<<endl;
                T.add(q[i].x,-1);
                break;
        }
    }
    system("pause");
    return 0;
}

用樹狀數組實現的平衡樹