【BZOJ 3224】普通*衡树

【原题题面】传送门

【题解大意】

*衡树模板题。

左旋右旋使数尽量满足左右子树相当的情况。

随机化权值是因为在随机数据下BST趋*于*衡。

同时要维护子树大小和样本容量来回答询问。

具体实现看代码。

【code】

#include<bits/stdc++.h>
using namespace std;
#define File1 "input"
#define File2 "output"
#define inf 0x7fffffff
#define ll long long
inline void file(){
    freopen(File1".in","r",stdin);
    freopen(File2".out","w",stdout);
}
inline int read(){
    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<<1)+(x<<3)+ch-'0'; ch=getchar();}
    return x*f;
}
const int mxn = 1e5+5;
int n;
struct node{
    int l,r,v,sz,cnt,dat;
}t[mxn];

int tot;//the number of point
inline int New(int v){
    t[++tot].v = v;
    t[tot].dat = rand();
    t[tot].cnt = t[tot].sz = 1;//new !
    return tot;
}

inline void Update(int p){
    t[p].sz = t[t[p].l].sz + t[t[p].r].sz + t[p].cnt;
}

int rt;
inline void Build(){
    New(-inf),New(inf);
    t[rt=1].r = 2;
    Update(rt);
}

inline void zig(int &y){
    int x = t[y].l;
    t[y].l = t[x].r;
    t[x].r = y;
    y = x;//y为引用,跟进行了修改,所以更改根
    Update(t[y].r),Update(y);//其实改的是此时的根
}
inline void zag(int &x){
    int y = t[x].r;
    t[x].r = t[y].l;
    t[y].l = x;
    x = y;//同理
    Update(t[x].l),Update(x);
}

inline void Insert(int &x,int v){
    if(x == 0){
        x = New(v);
        return;
    }//p借用rt值
    if(v == t[x].v){
        t[x].cnt ++;
        Update(x);
        return;
    }
    if(v < t[x].v){
        Insert(t[x].l,v);
        if(t[x].dat < t[t[x].l].dat) zig(x);
    }//left
    else{
        Insert(t[x].r,v);
        if(t[x].dat < t[t[x].r].dat) zag(x);
    }
    Update(x);
    return;
}

inline void Remove(int &x,int v){
    if(x == 0) return;
    if(v == t[x].v){
        if(t[x].cnt > 1){
            t[x].cnt--;
            Update(x);
            return;
        }else{
            if(t[x].l || t[x].r){
                if(t[x].r == 0 || t[t[x].l].dat > t[t[x].r].dat)
                    zig(x),Remove(t[x].r,v);
                else zag(x),Remove(t[x].l,v);
                Update(x);
            }
            else x = 0;
            return;
        }
    }
    v < t[x].v ? Remove(t[x].l,v):Remove(t[x].r,v);
    Update(x);
}

inline int Get_rk_By_v(int x,int v){
    if(x == 0) return 0;
    if(v == t[x].v) return t[t[x].l].sz + 1;
    if(v < t[x].v) return Get_rk_By_v(t[x].l,v);
    return Get_rk_By_v(t[x].r,v) + t[t[x].l].sz + t[x].cnt;
}

inline int Get_v_By_rk(int x,int rk){
    if(x == 0) return inf;
    if(t[t[x].l].sz >= rk) return Get_v_By_rk(t[x].l,rk);
    if(t[t[x].l].sz + t[x].cnt >= rk) return t[x].v;
    return Get_v_By_rk(t[x].r,rk-t[t[x].l].sz-t[x].cnt);
}

inline int Getpre(int v){
    int ans(1);
    int x = rt;
    while(x){
        if(v == t[x].v){
            if(t[x].l > 0){
                x = t[x].l;
                while(t[x].r > 0) x = t[x].r;
                ans = x;
            }
            break;
        }
        if(t[x].v < v && t[x].v > t[ans].v) ans = x;
        x = v < t[x].v ? t[x].l : t[x].r;
    }
    return t[ans].v;
}

inline int Getnxt(int v){
    int ans = 2;
    int x = rt;
    while(x){
        if(v == t[x].v){
            if(t[x].r > 0){
                x = t[x].r;
                while(t[x].l > 0) x = t[x].l;
                ans = x;
            }
            break;
        }
        if(t[x].v > v && t[x].v < t[ans].v) ans = x;
        x = v < t[x].v ? t[x].l : t[x].r;
    }
    return t[ans].v;
}

int main(){
//    file();
    Build();
    n = read();
    for(int i = 1;i <= n; ++i){
        int opt = read(),x = read();
        switch(opt){
            case 1:
                Insert(rt,x);
                break;
            case 2:
                Remove(rt,x);
                break;
            case 3:
                printf("%d\n",Get_rk_By_v(rt,x)-1);
                break;
            case 4:
                printf("%d\n",Get_v_By_rk(rt,x+1));
                break;
            case 5:
                printf("%d\n",Getpre(x));
                break;
            case 6:
                printf("%d\n",Getnxt(x));
                break;
        }
    }
    return 0;
}
/*
8
1 10
1 20
1 30
3 20
4 2
2 10
5 25
6 -1
*/
View Code

 

posted @ 2019-05-28 19:56  ve-2021  阅读(137)  评论(0编辑  收藏  举报