平衡树之splay BZOJ3224 普通平衡树

来源:互联网 发布:mac选择office安装路径 编辑:程序博客网 时间:2024/05/29 23:22

3224: Tyvj 1728 普通平衡树

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 12204  Solved: 5199
[Submit][Status][Discuss]

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.每个数的数据范围:[-2e9,2e9]

 

Source

平衡树

 

  1 /*f[i]表示i的父结点  2 ch[i][0]表示i的左儿子  3 ch[i][1]表示i的右儿子  4 key[i]表示i的关键字(即结点i代表的那个数字)  5 cnt[i]表示i结点的关键字出现的次数(相当于权值)  6 size[i]表示包括i的这个子树的大小  7 sz为整棵树的大小  8 root为整棵树的根编号   9 */ 10 //借用某神犇的话 没事就多转转  11 #include<iostream> 12 #include<cstdio> 13 #include<cstring> 14 #include<algorithm> 15 using namespace std; 16   17 const int maxn=100010; 18 int f[maxn],ch[maxn][2],key[maxn],cnt[maxn],size[maxn],sz,root; 19 int n,opt,num; 20   21 void clean(int x){//清空  22     ch[x][0]=ch[x][1]=f[x]=cnt[x]=key[x]=size[x]=0; 23 } 24   25 int get(int x){//判断当前点是左还是右  26     return ch[f[x]][1]==x;//?????? 27 } 28   29 void update(int x){//更新size值  30     if(x){ 31         size[x]=cnt[x]; 32         if(ch[x][0]) size[x]+=size[ch[x][0]]; 33         if(ch[x][1]) size[x]+=size[ch[x][1]]; 34     } 35     return; 36 } 37   38 void rotate(int x){ 39     int old=f[x]; 40     int oldf=f[old]; 41     int which=get(x); 42     ch[old][which]=ch[x][which^1]; 43     f[ch[old][which]]=old; 44     f[old]=x; 45     ch[x][which^1]=old; 46     f[x]=oldf; 47     if(oldf) ch[oldf][ch[oldf][1]==old]=x; 48     update(old); 49     update(x);  50 } 51   52 void splay(int x){  53     for(int fa;fa=f[x];rotate(x)) 54         if(f[fa]) rotate((get(x)==get(fa)?fa:x)); 55     root=x; 56 } 57   58 int find(int v){//查询某数的排名  59     int ans=0; 60     int now=root; 61     while(1){ 62         if(v<key[now]){ 63             now=ch[now][0]; 64         } 65         else{ 66             ans+=(ch[now][0]?size[ch[now][0]]:0); 67             if(v==key[now]){ 68                 splay(now); 69                 return ans+1; 70             } 71             ans+=cnt[now]; 72             now=ch[now][1]; 73         } 74     } 75 } 76   77 int findx(int x){//查找排名为x的数  78     int now=root; 79     while(1){ 80         if(ch[now][0]&&x<=size[ch[now][0]]) now=ch[now][0]; 81         else{ 82             int temp=(ch[now][0]?size[ch[now][0]]:0)+cnt[now]; 83             if(x<=temp) return key[now]; 84             x-=temp; 85             now=ch[now][1]; 86         } 87     } 88 } 89   90 int pre(){ 91     int now=ch[root][0]; 92     while(ch[now][1]) now=ch[now][1]; 93     return now; 94 } 95   96 int next(){ 97     int now=ch[root][1]; 98     while(ch[now][0]) now=ch[now][0]; 99     return now; 100 }101  102 void del(int x){103     int whatever=find(x);104     if(cnt[root]>1){105         cnt[root]--;106         return;107     }108     if(!ch[root][0]&&!ch[root][1]){109         clean(root);110         root=0;111         return;112     }113     if(!ch[root][0]){114         int oldroot=root;115         root=ch[root][1];116         f[root]=0;117         clean(oldroot);118         return;119     }120     else if(!ch[root][1]){121         int oldroot=root;122         root=ch[root][0];123         f[root]=0;124         clean(oldroot);125         return;126     }127     int leftbig=pre();128     int oldroot=root;129     splay(leftbig);130     f[ch[oldroot][1]]=root;131     ch[root][1]=ch[oldroot][1];132     clean(oldroot);133     update(root);134     return;135 }136  137 void insert(int v){138     if(!root){139         sz++;140         ch[sz][0]=ch[sz][1]=f[sz]=0;141         key[sz]=v;142         cnt[sz]=1;143         size[sz]=1;144         root=sz;145         return;146     }147     int now=root;148     int fa=0;149     while(1){150         if(key[now]==v){151             cnt[now]++;152             update(fa);153             splay(now);154             break;155         }156         fa=now;157         now=ch[now][key[now]<v];//??????158         if(now==0){159             sz++;160             ch[sz][0]=ch[sz][1]=0;161             f[sz]=fa;162             key[sz]=v;163             cnt[sz]=1;164             ch[fa][key[fa]<v]=sz;165             update(fa);166             splay(sz);167             break;168         }169     }170     return;171 } 172  173 int main(){174     scanf("%d",&n);175     for(int i=1;i<=n;i++){176         scanf("%d%d",&opt,&num);177         if(opt==1) insert(num);178         if(opt==2) del(num);179         if(opt==3) printf("%d\n",find(num));180         if(opt==4) printf("%d\n",findx(num));181         if(opt==5){182             insert(num);183             printf("%d\n",key[pre()]);184             del(num);185         } 186         if(opt==6){187             insert(num);188             printf("%d\n",key[next()]);189             del(num);190         }191     }192     return 0;193 }

 

 

存作模板

原创粉丝点击