zoukankan      html  css  js  c++  java
  • P3369 【模板】普通平衡树(Treap/SBT)

    题目描述

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

    1. 插入x数

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

    3. 查询x数的排名(若有多个相同的数,因输出最小的排名)

    4. 查询排名为x的数

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

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

    输入输出格式

    输入格式:

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

    输出格式:

    对于操作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<=100000

    2.每个数的数据范围:[-1e7,1e7]

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

    在此鸣谢

    代码

    #include<cstdio>
    #define N 100010
    using namespace std;
    
    int fa[N],ch[N][2],siz[N],cnt[N],date[N],root,nn,n,tot;
    
    int son(int x) {
        return x==ch[fa[x]][1];
    }
    
    void pushup(int rt) {
        int l=ch[rt][0],r=ch[rt][1];
        siz[rt]=siz[l]+siz[r]+cnt[rt];
    }
    
    void rotate(int x) {
       int y=fa[x],z=fa[y],b=son(x),c=son(y),a=ch[x][!b];
       if(z)ch[z][c]=x;else root=x;fa[x]=z;
       if(a)fa[a]=y;ch[y][b]=a;
       ch[x][!b]=y;fa[y]=x;///
       pushup(y);pushup(x);    
    }
    
    void splay(int x,int i) {
        while(fa[x]!=i) {
            int y=fa[x],z=fa[y];
            if(z==i) {
                rotate(x);
            } else {
                if(son(x)==son(y)) {
                    rotate(y);rotate(x);
                } else {
                    rotate(x);rotate(x);
                }
            }
        }
    }
    
    void ins(int &rt,int x) {
        if(rt==0) {
            rt=++nn;
            date[nn]=x;
            siz[nn]=cnt[nn]=1;
            return;
        }
        if(x==date[rt]) {
            cnt[rt]++;siz[rt]++;
            return;
        }
        if(x<date[rt]) {
            ins(ch[rt][0],x);
            fa[ch[rt][0]]=rt;
            pushup(rt);
        } else {
            ins(ch[rt][1],x);
            fa[ch[rt][1]]=rt;
            pushup(rt);
        }
    }
    
    int getpre(int rt,int x) {
        int p=rt,ans;
        while(p) {
          if(x<=date[p]) {
              p=ch[p][0];///
          } else {
              ans=p;
              p=ch[p][1];
          }
        }
        return ans;
    }
    
    int getsuc(int rt,int x) {
        int p=rt,ans;
        while(p) {
            if(x>=date[p]) {
                p=ch[p][1];
            } else {
                ans=p;
                p=ch[p][0];
            }
        }
        return ans;
    }
    
    int getmn(int rt) {
        int p=rt,ans=-1;
        while(p) {
            ans=p;
            p=ch[p][0];
        }
        return ans;
    }
    
    void del(int rt,int x) {
        if(date[rt]==x) {
            if(cnt[rt]>1) {
                cnt[rt]--;siz[rt]--;
            } else {
                splay(rt,0);
                int p=getmn(ch[rt][1]);
                if(p!=-1) {
                    splay(p,rt);
                    root=p;fa[p]=0;
                    ch[p][0]=ch[rt][0];fa[ch[rt][0]]=p;
                    pushup(p);
                } else {
                    root=ch[rt][0];fa[ch[rt][0]]=0;
                }
            }
            return;
        }
        if(x<date[rt]) {
            del(ch[rt][0],x);
            pushup(rt);///
        } else {
            del(ch[rt][1],x);
            pushup(rt);
        }
    }
    
    int getk(int rt,int k) {
        if(date[rt]==k) {
            splay(rt,0);
            if(ch[rt][0]==0) {
                return 1;
            } else {
                return siz[ch[rt][0]]+1;
            }
        }
        if(k<date[rt]) return getk(ch[rt][0],k);
        else return getk(ch[rt][1],k);
    }
    
    int getkth(int rt,int k) {
        int l=ch[rt][0];
        if(siz[l]+1<=k&&k<=siz[l]+cnt[rt]) return date[rt];
        if(k<siz[l]+1) return getkth(ch[rt][0],k);
        if(siz[l]+cnt[rt]<k) return getkth(ch[rt][1],k-(siz[l]+cnt[rt]));
    }
    
    int main() {
        scanf("%d",&n);
        while(n--) {
            int opt,x;
            scanf("%d%d",&opt,&x);
            if(opt==1) {
                tot++;
                ins(root,x);
            }
            if(opt==2) {
                tot--;
                del(root,x);
            }
            if(opt==3) {
                printf("%d
    ",getk(root,x));
            }
            if(opt==4) {
                printf("%d
    ",getkth(root,x));
            }
            if(opt==5) {
                printf("%d
    ",date[getpre(root,x)]);
            }
            if(opt==6) {
                printf("%d
    ",date[getsuc(root,x)]);
            }
        }
        return 0;
    }
  • 相关阅读:
    MFC 时钟 计算器 日期天数计算
    test10
    test9
    iOS 防止按钮快速点击造成多次响应的避免方法
    NSBundle读取图片 plist文件和txt文件
    按指定格式的子字符串,删除和分割字符串
    python批处理入门知识点
    命令行ffmpeg批量旋转视频
    NSData转化成十六进制字符串
    xcode里面使用Memory Leaks和Instruments检测内存泄漏
  • 原文地址:https://www.cnblogs.com/zzyh/p/7257305.html
Copyright © 2011-2022 走看看