• 【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
    ",Get_rk_By_v(rt,x)-1);
                    break;
                case 4:
                    printf("%d
    ",Get_v_By_rk(rt,x+1));
                    break;
                case 5:
                    printf("%d
    ",Getpre(x));
                    break;
                case 6:
                    printf("%d
    ",Getnxt(x));
                    break;
            }
        }
        return 0;
    }
    /*
    8
    1 10
    1 20
    1 30
    3 20
    4 2
    2 10
    5 25
    6 -1
    */
    View Code
  • 相关阅读:
    QT调用其他UI并使用QLabel(text)
    QT调用单例模式脚本
    QT 调用另一个UI实现方式
    QT 键值
    (一) Mybatis 源码解析之源码概述
    设计模式之 模板模式开发
    十二、线程池
    (十一)并发容器ConcurrentHashMap
    mybatis plus 踩坑记 -- 自动填充
    C/C++ file
  • 原文地址:https://www.cnblogs.com/ve-2021/p/10939848.html
Copyright © 2020-2023  润新知