splay 模板(4843: Lydsy3224 普通平衡树)

Description

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)

Input

第一行为n,表示操作的个数
下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)
1.n的数据范围:n<=100000
2.每个数的数据范围:[-2e9,2e9]

Output

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

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

const int maxn=100000+10;
int ch[maxn][2],size_[maxn],cnt[maxn],key[maxn],root,sz,f[maxn];

void clear(int x){
     ch[x][1]=ch[x][0]=size_[x]=cnt[x]=key[x]=f[x]=0;
}

void update(int x){
     if(x){
        size_[x]=cnt[x];
        if(ch[x][0]) size_[x]+=size_[ch[x][0]];
        if(ch[x][1]) size_[x]+=size_[ch[x][1]];
     }
}

bool get(int x){
     return ch[f[x]][1]==x;
}

void Rotate(int x){
     int old=f[x],oldf=f[old],which=get(x);
     ch[old][which]=ch[x][which^1];
     f[ch[old][which]]=old;
     ch[x][which^1]=old;
     f[old]=x;
     f[x]=oldf;
     if(oldf){
        ch[oldf][ch[oldf][1]==old]=x;
     }
     update(old);
     update(x);
}

void splay(int x){
     for (int fa;(fa=f[x]);Rotate(x)){
          if(f[fa]) {
            Rotate(get(x)==get(fa)?fa:x);
          }
     }
     root=x;
}

void myinsert(int x){
     if(root==0){
        sz++,key[sz]=x,root=sz,f[sz]=ch[sz][0]=ch[sz][1]=0,cnt[sz]=1,size_[sz]=1;
        return ;
     }
     int now=root,fa=0;
     while(1){
        if(key[now]==x){
            cnt[now]++;
            update(now);
            update(fa);
            splay(now);
            break;
        }
        fa=now;
        now=ch[now][key[now]<x];
        if(now==0){
            sz++;
            ch[sz][0]=ch[sz][1]=0;
            f[sz]=fa;
            size_[sz]=cnt[sz]=1;
            key[sz]=x;
            ch[fa][key[fa]<x]=sz;
            update(fa);
            splay(sz);
            break ;
        }
     }
}

int findx(int x){
     int ans=0,now=root;
     while(1){
        if(x<key[now]) now=ch[now][0];
        else {
            ans+=(ch[now][0]?size_[ch[now][0]]:0);
            if(x==key[now]){ans+=1;splay(now);return ans;}
            ans+=cnt[now];
            now=ch[now][1];
        }
     }
}

int whox(int x){
    int now=root;
    while(1){
        if(ch[now][0]&&x<=size_[ch[now][0]]) now=ch[now][0];
        else{
            int temp=(ch[now][0]?size_[ch[now][0]]:0)+cnt[now];
            if(x<=temp) return key[now];
            x-=temp;
            now=ch[now][1];
        }
    }
}

int pre(){
    int now=ch[root][0];
    while(ch[now][1]) now=ch[now][1];
    return now;
}

int next(){
    int now=ch[root][1];
    while(ch[now][0]) now=ch[now][0];
    return now;
}

void del(int x){
      int pp=findx(x);
     if(cnt[root]>1) {cnt[root]--;update(root);return ;}
     if(!ch[root][0]&&!ch[root][1]){
        clear(root);
        root=0;
        return ;
     }
     if(!ch[root][0]){
        int oldroot=root;
        root=ch[root][1];
        f[root]=0;
        clear(oldroot);
        return ;
     }
     else if(!ch[root][1]){
        int oldroot=root;
        root=ch[root][0];
        f[root]=0;
        clear(oldroot);
        return ;
     }
     int oldroot=root,qian=pre();
     splay(qian);
     ch[root][1]=ch[oldroot][1];
     f[ch[oldroot][1]]=root;
     clear(oldroot);
     update(root);
}

int main(){
    int n;
    scanf("%d",&n);
    int op,x;
    while(n--){
        scanf("%d%d",&op,&x);
        if(op==1) myinsert(x);
        if(op==2) del(x);
        if(op==3) printf("%d\n",findx(x));
        if(op==4) printf("%d\n",whox(x));
        if(op==5) {
                myinsert(x);
                printf("%d\n",key[pre()]);
                del(x);
        }
        if(op==6){
            myinsert(x);
            printf("%d\n",key[next()]);
            del(x);
        }
    }
return 0;
}

 

posted @ 2018-03-21 19:15  lmjer  阅读(184)  评论(0编辑  收藏  举报