• 【模板】普通平衡树(Treap/SBT)


    题目描述

    您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:

    1. 插入x数

    2. 删除x数(若有多个相同的数,因只删除一个)

    3. 查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)

    4. 查询排名为x的数

    5. 求x的前驱(前驱定义为小于x,且最大的数)

    6. 求x的后继(后继定义为大于x,且最小的数)

    输入输出格式

    输入格式:

    第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号( 1 leq opt leq 61opt6 )

    输出格式:

    对于操作3,4,5,6每行输出一个数,表示对应答案

    #include <bits/stdc++.h>
    
    using namespace std;
    const int maxn = 100000+5;
    const int inf = 2000000008;
    int root,tot;
    struct Splay{
        int ch[maxn][2],fa[maxn],siz[maxn],key[maxn], same[maxn];
    
        void init(int t, int val = 0, int par = 0){
            ch[t][0] = ch[t][1] = 0; key[t] = val;same[t] = 1; fa[t] = par;
        }
        void up(int t){
            siz[t] = siz[ch[t][1]] + siz[ch[t][0]] + same[t];
        }
        void init(){
            init(0, 0, 0);
            tot = root = 0;
        }
        void rotate(int x, int d){
            int y = fa[x];
            ch[y][d^1] = ch[x][d];
            if(ch[x][d])fa[ch[x][d]] = y;
            fa[x] = fa[y];
            if(fa[y]){
                if(y == ch[fa[y]][0])ch[fa[y]][0] = x;
                else ch[fa[y]][1] = x;
            }
            ch[x][d] = y;fa[y] = x;
            up(y);    // father first
            up(x);            
        }
        void splay(int x, int targrt){
    
            while(fa[x] != targrt){
                int y = fa[x];
                if(x == ch[y][0]){
                    if(targrt != fa[y] && y == ch[fa[y]][0])
                        rotate(y, 1);
                    rotate(x, 1);
                }
                else {
                    if(targrt != fa[y]&& y == ch[fa[y]][1])
                        rotate(y, 0);
                    rotate(x, 0);
                }
            }
            if(!targrt)root = x;
        }
        void insert( int x,int t = root, int par = 0){
            if(!t){
                t = ++tot;
                init(t, x, par);
                ch[par][x > key[par]] = t;
                splay(t, 0);
            }
            else{
                if(x == key[t]){
                same[t]++;    
                up(t);   //! 
                }
                else if(x < key[t]){
                    insert(x, ch[t][0], t);
                    up(t);
                }
                else {
                    insert(x, ch[t][1], t);
                    up(t);
                }
            }
            
        }
    
        int rank(int x,int t = root){
            if(!t)return 0;
            if(x == key[t])return siz[ch[t][0]]+1;
            if(x < key[t])return rank(x, ch[t][0]);
            return siz[ch[t][0]]+same[t]+rank(x, ch[t][1]);
        }
        int query(int x, int t = root){
            if(!x)return t;        
            if(x > siz[ch[t][0]] + same[t])
                return query(x - same[t] - siz[ch[t][0]], ch[t][1]);
            if(x <= siz[ch[t][0]])return query(x, ch[t][0]);
            return t;   
            
        }
        void Query(int x){
            printf("%d
    ",key[query(x)]);
        }
        void erase(int x){
            int t = root;
            while(key[t] != x)t = ch[t][x > key[t]];        
            splay(t, 0);
            if(same[t]>1){         
                same[t]--;
                up(t); //!
                return;
            }
            same[t] = 0;
            int y = ch[t][1];
            bool b;
            if(!y)y = ch[root][0], b = 1;
            else b = 0;
            if(!y)root = 0,same[t] = 0;//有可能只有一个节点
            while(ch[y][b])y = ch[y][b];
            splay(y, root);
            ch[y][b] = ch[root][b];
            if(ch[root][b]) fa[ch[root][b]] = y;
            fa[y] = 0; root = y;
            up(y);  //!
        }
    
        int getpre(int x){
            int ret = -inf, t = root;
            while(t){
                if(key[t] < x)ret = max(ret, key[t]);
                t = ch[t][x > key[t]];
            }
            return ret;
        }
        int getscc(int x){
            int ret = inf, t = root;
            while(t){
                if(key[t] > x)
                    ret = min(ret, key[t]);
                t = ch[t][x >=key[t]];
            }
            return ret;
        }
       void print(){
            for(int i = 1; i <= tot; i++)
                printf("%d %d %d
    ",i, ch[i][0], ch[i][1]);
       }
    }Tr;
    int main()
    {
        int n;
        scanf("%d",&n);
        Tr.init();
        while(n--){
            int opt,x;
            scanf("%d%d",&opt,&x);
            switch(opt){
                case 1:Tr.insert(x);break;
                case 2:Tr.erase(x);break;
                case 3:printf("%d
    ",Tr.rank(x));break;
                case 4:Tr.Query(x);break;
                case 5:printf("%d
    ",Tr.getpre(x));break;
                case 6:printf("%d
    ",Tr.getscc(x));break;
            }
            //Tr.print();
        }
        return 0;
    }
  • 相关阅读:
    HDU 1097 a hard puzzle
    HDU 4588 Count The Carries
    不想用锐捷怎么办?锐捷出问题|锐捷不能用怎么办?用menohust代替吧
    线段树及其变种的相关资料(不定期更新)
    UVa 10075
    UVa 1301
    UVa 10256
    UVa 1453
    计算几何相关资料+题目推荐(不定期补充)
    UVa 11524
  • 原文地址:https://www.cnblogs.com/EdSheeran/p/8688547.html
Copyright © 2020-2023  润新知