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\n",getk(root,x));
        }
        if(opt==4) {
            printf("%d\n",getkth(root,x));
        }
        if(opt==5) {
            printf("%d\n",date[getpre(root,x)]);
        }
        if(opt==6) {
            printf("%d\n",date[getsuc(root,x)]);
        }
    }
    return 0;
}
复制代码

 

posted @   ANhour  阅读(242)  评论(0编辑  收藏  举报
努力加载评论中...
点击右上角即可分享
微信分享提示