普通平衡树(bzoj 3224)

Description

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

Input

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

Output

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

Sample Input

10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598

Sample Output

106465
84185
492737

HINT

 

1.n的数据范围:n<=100000

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

数据如下http://pan.baidu.com/s/1jHMJwO2
/*
  一个平衡树的模板写了一上午了,能犯的错误基本都犯了。。。
  首先没加哨兵,再就是删除操作时没有更新sz(这个巨坑),真是长记性了。 
*/
#include<cstdio>
#include<iostream>
#define N 100010
using namespace std;
int son[N][2],fa[N],val[N],cnt[N],sz[N],m,rt,size;

void pushup(int x){
    sz[x]=sz[son[x][0]]+sz[son[x][1]]+cnt[x];
}

void rotate(int x,int &k){
    int y=fa[x],z=fa[y],l,r;
    if(son[y][0]==x) l=0;else l=1;r=l^1;
    if(y==k) k=x;
    else {
        if(son[z][0]==y) son[z][0]=x;
        else son[z][1]=x;
    }
    fa[x]=z;fa[y]=x;fa[son[x][r]]=y;
    son[y][l]=son[x][r];son[x][r]=y;
    pushup(y);pushup(x);
}

void splay(int x,int &k){
    while(x!=k){
        int y=fa[x],z=fa[y];
        if(y!=k){
            if((son[y][0]==x)^(son[z][0]==y)) rotate(x,k);
            else rotate(y,k);
        }
        rotate(x,k);
    }
}

void insert(int v){
    int k=rt,y=0;
    while(k&&val[k]!=v) y=k,k=son[k][v>val[k]];
    if(k) cnt[k]++;
    else {
        k=++size;sz[k]=1;cnt[k]=1;fa[k]=y;val[k]=v;
        if(y) son[y][v>val[y]]=k;
    }
    splay(k,rt);
}

void find1(int v){//查找v的位置 
    int k=rt;if(!k)return;
    while(son[k][v>val[k]]&&val[k]!=v) 
      k=son[k][v>val[k]];
    splay(k,rt);
}

int find2(int x){//查找排名为x的数 
    x++;
    int k=rt;
    if(sz[k]<x)return 0;
    while(1){
        if(sz[son[k][0]]<x&&sz[son[k][0]]+cnt[k]>=x) return k;
        if(sz[son[k][0]]>=x) k=son[k][0];
        else x-=(sz[son[k][0]]+cnt[k]),k=son[k][1];
    }
    return k;
}

int nxt(int x,int f){
    find1(x);
    if((val[rt]>x&&f)||val[rt]<x&&!f) return rt;
    int p=son[rt][f];
    while(son[p][f^1]) p=son[p][f^1];
    return p;
}

void del(int v){
    find1(v);
    int x=rt,k;
    if(cnt[x]>1){cnt[x]--;sz[x]--;return;}
    if(!son[x][0]||!son[x][1]){
        rt=son[x][0]+son[x][1];
    }
    else {
        k=son[x][1];
        while(son[k][0])k=son[k][0];sz[k]+=sz[son[x][0]];
        fa[son[x][0]]=k;son[k][0]=son[x][0];
        rt=son[x][1];
    }
    fa[rt]=0;splay(k,rt);
}

int main(){
    insert(-0x7fffffff);insert(0x7fffffff);
    scanf("%d",&m);
     for(int i=1;i<=m;i++){
        int opt,x;scanf("%d%d",&opt,&x);
        if(opt==1) insert(x);
        if(opt==2) del(x);
        if(opt==3) find1(x),printf("%d\n",sz[son[rt][0]]);
        if(opt==4) printf("%d\n",val[find2(x)]);
        if(opt==5) printf("%d\n",val[nxt(x,0)]);
        if(opt==6) printf("%d\n",val[nxt(x,1)]);
    }
    return 0;
}

 

posted @ 2017-02-15 21:50  karles~  阅读(243)  评论(1编辑  收藏  举报