用树状数组实现的平衡树

一、题目:

洛谷模板

二、思路:

用树状数组实现的平衡树,实现起来很简单,但有很多细节需要考虑。

维护一个权值树状数组,查排名时直接前缀和,前驱、后继都很简单。比较难的是已知排名求值,需要倍增。

怎么能写二分呢?倍增比二分快几百倍。——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;
}
原文地址:https://www.cnblogs.com/little-aztl/p/9746207.html