• 洛谷 P3369 【模板】普通平衡树(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每行输出一个数,表示对应答案

     

    输入输出样例

    输入样例#1:
    10
    1 106465
    4 1
    1 317721
    1 460929
    1 644985
    1 84185
    1 89851
    6 81968
    1 492737
    5 493598
    输出样例#1:
    106465
    84185
    492737

    说明

    时空限制:1000ms,128M

    1.n的数据范围: n leq 100000n100000

    2.每个数的数据范围: [-{10}^7, {10}^7][107​​,107​​]

    来源:Tyvj1728 原名:普通平衡树

    在此鸣谢

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define MAXN 100001
    using namespace std;
    int se,root,siz[MAXN],fa[MAXN],ch[MAXN][2],key[MAXN],cnt[MAXN];
    void update(int x){
        siz[x]=cnt[x];
        if(ch[x][0])    siz[x]+=siz[ch[x][0]];
        if(ch[x][1])    siz[x]+=siz[ch[x][1]];
    }
    int getson(int x){
        return ch[fa[x]][1]==x;
    }
    void rotate(int x){
        int f=fa[x],ff=fa[f],k=getson(x);
        ch[f][k]=ch[x][k^1];fa[ch[f][k]]=f;
        ch[x][k^1]=f;fa[f]=x;
        fa[x]=ff;
        if(ff)    ch[ff][ch[ff][1]==f]=x;
        update(f);
        update(x);
    }
    void splay(int x){
        for(int f;f=fa[x];rotate(x))
            if(fa[f])
                rotate(getson(x)==getson(f)?f:x);
        root=x;
    }
    void create(int x){
        se++;
        key[se]=x;
        siz[se]=cnt[se]=1;
        ch[se][1]=ch[se][0]=fa[se]=0; 
    }
    void insert(int x){
        if(!root){
            create(x);
            root=se;
        }
        else{
            int now=root,f=0;
            while(1){
                if(key[now]==x){
                    cnt[now]++;
                    siz[now]++;
                    splay(now);
                    break;
                }
                f=now;
                now=ch[f][x>key[f]];
                if(!now){
                    create(x);
                    fa[se]=f;
                    ch[f][x>key[f]]=se;
                    splay(se);
                    break;
                }
            }
        }
    }
    int findpos(int x){
        int now=root,ans=0;
        while(1){
            if(x<key[now])
                now=ch[now][0];
            else{
                ans+=siz[ch[now][0]];
                if(x==key[now]){
                    splay(now);
                    return ans+1;
                }
                ans+=cnt[now];
                now=ch[now][1];
            }
        }
    }
    int findx(int x){
        int now=root;
        while(1){
            if(ch[now][0]&&x<=siz[ch[now][0]])
                now=ch[now][0];
            else{
                int tmp=(ch[now][0]?siz[ch[now][0]]:0)+cnt[now];
                if(x<=tmp)    return key[now];
                x-=tmp;
                now=ch[now][1];
                    
            }
        }
    }
    int pre(){
        int now=ch[root][0];
        while(ch[now][1])
            now=ch[now][1];
        return now;
    }
    int net(){
        int now=ch[root][1];
        while(ch[now][0])
            now=ch[now][0];
        return now;
    }
    void clear(int x){
        fa[x]=siz[x]=ch[x][0]=ch[x][1]=cnt[x]=key[x]=0;
    }
    void deletee(int x){
        int t=findpos(x);
        if(cnt[root]>1){
            cnt[root]--;
            siz[root]--;
            return ;
        }
        if(!ch[root][0]&&!ch[root][1]){
            clear(root);
            root=0;
            return ;
        }
        if(!ch[root][1]){
            int tmp=root;
            root=ch[root][0];
            fa[root]=0;
            clear(tmp);
            return ;
        }
        if(!ch[root][0]){
            int tmp=root;
            root=ch[root][1];
            fa[root]=0;
            clear(tmp);
            return ;
        }
        int prel=pre(),tmp=root;
        splay(prel);
        ch[root][1]=ch[tmp][1];
        fa[ch[tmp][1]]=root;
        clear(tmp);
        update(root);
    }
    int main(){
        int n,opt,x;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d%d",&opt,&x);
            if(opt==1)    insert(x);
            if(opt==2)    deletee(x);
            if(opt==3)    cout<<findpos(x)<<endl;
            if(opt==4)    cout<<findx(x)<<endl;
            if(opt==5){
                insert(x);
                cout<<key[pre()]<<endl;
                deletee(x);
            }
            if(opt==6){
                insert(x);
                cout<<key[net()]<<endl;
                deletee(x);
            }
        }
    }
    细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。 雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。
  • 相关阅读:
    Educational Codeforces Round 81 (Rated for Div. 2) A-E
    SEERC 2018 I
    manjaro linux java环境配置
    Pangu and Stones HihoCoder
    Linux下 vim 的配置
    C++内存管理技术
    Interview_C++_day27
    Interview_C++_day26
    Interview_C++_day25
    Interview_数据库_day24
  • 原文地址:https://www.cnblogs.com/cangT-Tlan/p/7582980.html
Copyright © 2020-2023  润新知