[BZOJ 3224] [Tyvj 1728] 普通平衡树

3224: Tyvj 1728 普通平衡树

Time Limit: 10 Sec
Memory Limit: 128 MB

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]
【题解】
平衡树模板题目。
  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int N=100010;
  4 int fa[N],ch[N][2],root,k[N],ind=0,size[N];
  5 void zig(int x) {  
  6     int y=fa[x],z=fa[y];  
  7     fa[y]=x;
  8     fa[x]=z;  
  9     ch[y][0]=ch[x][1],fa[ch[x][1]]=y,ch[x][1]=y;  
 10     if (y==ch[z][0]) ch[z][0]=x;  
 11     else ch[z][1]=x;  
 12     size[y]=size[ch[y][0]]+size[ch[y][1]]+1; 
 13 }  
 14 void zag(int x) {  
 15     int y=fa[x],z=fa[y];  
 16     fa[y]=x,fa[x]=z; 
 17     ch[y][1]=ch[x][0],fa[ch[x][0]]=y,ch[x][0]=y;  
 18     if (y==ch[z][0]) ch[z][0]=x;  
 19     else ch[z][1]=x;  
 20     size[y]=size[ch[y][0]]+size[ch[y][1]]+1; 
 21 }  
 22 void splay(int x,int s) {
 23     while (fa[x]!=s) {  
 24         int y=fa[x],z=fa[y];  
 25         if (z==s) {  
 26             if (x==ch[y][0]) zig(x);  
 27             else zag(x);  
 28             break;  
 29         }  
 30         if (y==ch[z][0]) {
 31             if (x==ch[y][0]) zig(y),zig(x);  
 32             else zag(x),zig(x);  
 33         }  
 34         else {  
 35             if (x==ch[y][1]) zag(y),zag(x);  
 36             else zig(x),zag(x);  
 37         }  
 38     }  
 39     size[x]=size[ch[x][0]]+size[ch[x][1]]+1; 
 40     if (s==0) root=x;
 41 }  
 42 inline void newnode(int &x,int fax,int key) {
 43     x=++ind;
 44     ch[x][0]=ch[x][1]=0;
 45     fa[x]=fax;
 46     k[x]=key;
 47 }
 48 inline int search(int w) {
 49     int p,x=root;
 50     while(x) {
 51         p=x;
 52         if(k[x]>w) x=ch[x][0];
 53         else x=ch[x][1];
 54     }
 55     return p;
 56 }
 57 inline void ins(int w){
 58     if (root==0) {
 59         newnode(root,0,w);
 60         return ;
 61     }
 62     int i=search(w);
 63     if(w<k[i]) newnode(ch[i][0],i,w);
 64     else newnode(ch[i][1],i,w);
 65     splay(ind,0);
 66 }
 67 int getsm(int w) {
 68     int x=root,ans=ind+1;
 69     while(x) {
 70         if (k[x]>w) {x=ch[x][0];continue;}
 71         if (k[x]<w) {x=ch[x][1];continue;}
 72         if (k[x]==w) {
 73             ans=x;
 74             x=ch[x][0];
 75         }
 76     }
 77     if (ans==ind+1) return -1;
 78     return ans;
 79 }
 80 inline int getmax(int x) {while(ch[x][1]) x=ch[x][1]; return x;}
 81 inline int getmin(int x) {while(ch[x][0]) x=ch[x][0]; return x;}
 82 inline int getpre(int x) {return getmax(ch[root][0]);}
 83 inline int getnext(int x) {return getmin(ch[root][1]);}
 84 inline void del(int w) {
 85     int x=getsm(w);
 86     splay(x,0);
 87     int pp=getpre(x),nn=getnext(x);
 88     splay(pp,0);splay(nn,root);
 89     int y=fa[x];
 90     fa[x]=0;
 91     if(x==ch[y][0]) ch[y][0]=0;
 92     else ch[x][0]=0;
 93     size[y]=size[ch[y][0]]+size[ch[y][1]]+1;
 94     size[root]=size[ch[root][0]]+size[ch[root][1]]+1;
 95 }
 96 inline int ffind(int w) {
 97     int x=getsm(w);
 98     splay(x,0);
 99     return size[ch[x][0]];
100 }
101 int findkth(int x,int kth) {
102     int s=size[ch[x][0]];
103     if(kth==s+1) return k[x];
104     if(s>=kth) return findkth(ch[x][0],kth);
105     else return findkth(ch[x][1],kth-s-1);
106 }
107 int getp(int w) {
108     int y=getsm(w);
109     ins(w);
110     if(y!=-1) splay(y,0);
111     int ans=getmax(ch[root][0]);
112     del(w);
113     return k[ans];
114 }
115 int getn(int w) {
116     ins(w);
117     int ans=getmin(ch[root][1]);
118     del(w);
119     return k[ans];
120 }
121 int main() {
122     int q;
123     root=0;
124     ins(-5000000);ins(5000000);
125     scanf("%d",&q);  
126     while (q--) {  
127         int x,k;  
128         scanf("%d%d",&x,&k);  
129         if (x==1) ins(k);  
130         else if (x==2) del(k);  
131         else if (x==3) printf("%d\n",ffind(k));  
132         else if (x==4) printf("%d\n",findkth(root,k+1));  
133         else if (x==5) printf("%d\n",getp(k));  
134         else if (x==6) printf("%d\n",getn(k));  
135     }
136     return 0;
137 }
View Code

还是习惯分开来写Zig-Zag

posted @ 2015-06-16 20:32  TonyFang  阅读(301)  评论(0编辑  收藏  举报