Splay 模板

 

  今天2.12,我发现下面的代码有bug(bug在delete()里,有些情况没有考虑到),对于bzoj3224可以过,但是改造一下过不了NOI2004郁闷的出纳员,目前又改了两天把我写的最靠谱的代码放在最下面。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstdlib>
  4 #include<cmath>
  5 #include<algorithm>
  6 #include<queue>
  7 #include<vector>
  8 using namespace std;
  9 const int maxn=200000;
 10 int key[maxn],lc[maxn],rc[maxn],fa[maxn],siz[maxn];
 11 int tot,root;
 12 int T;
 13 void update(int x){
 14     siz[x]=siz[lc[x]]+1+siz[rc[x]];
 15 }
 16 void r_rotate(int x){
 17     int y=fa[x];
 18     lc[y]=rc[x]; fa[rc[x]]=y; fa[x]=fa[y];
 19     if(y==lc[fa[y]]) lc[fa[y]]=x;
 20     else rc[fa[y]]=x;
 21     fa[y]=x; rc[x]=y;
 22     update(x); update(y);
 23 }
 24 void l_rotate(int x){
 25     int y=fa[x];
 26     rc[y]=lc[x]; fa[lc[x]]=y; fa[x]=fa[y];
 27     if(y==lc[fa[y]]) lc[fa[y]]=x;
 28     else rc[fa[y]]=x;
 29     fa[y]=x; lc[x]=y;
 30     update(x); update(y);
 31 }
 32 void splay(int x,int s){
 33     int p;
 34     while(fa[x]!=s){
 35         p=fa[x];
 36         if(fa[p]==s){
 37             if(x==lc[p]) r_rotate(x);
 38             else l_rotate(x);
 39             break; 
 40         }
 41         if(x==lc[p]){
 42             if(p==lc[fa[p]]) r_rotate(p),r_rotate(x);
 43             else r_rotate(x),l_rotate(x);
 44         }
 45         else{
 46             if(p==rc[fa[p]]) l_rotate(p),l_rotate(x);
 47             else l_rotate(x),r_rotate(x);
 48         }
 49     }
 50     if(s==0) root=x;
 51     update(x);
 52 }
 53 int find(int v){//查找在这棵树中键值为v的节点 
 54     int x=root;
 55     while(x!=0){
 56         if(v<key[x]) x=lc[x];
 57         else if(v>key[x]) x=rc[x];
 58         else if(v==key[x]){
 59             splay(x,0);
 60             return x;
 61         }
 62     }
 63     return -1;
 64 }
 65 void New_node(int &x,int fath,int v){//建立新节点 
 66     x=++tot;
 67     lc[x]=rc[x]=0; siz[x]=1;
 68     fa[x]=fath;
 69     key[x]=v;
 70 }
 71 void insert(int v){//插入新节点 
 72     if(root==0){
 73         New_node(root,0,v);
 74         return ;
 75     }
 76     int p,x=root;
 77     while(x!=0){
 78         p=x;
 79         if(v<=key[x]) siz[x]++,x=lc[x];
 80         else siz[x]++,x=rc[x];
 81     }
 82     if(v<=key[p]) New_node(lc[p],p,v);
 83     else New_node(rc[p],p,v);
 84     splay(tot,0);
 85 }
 86 int getmax(int x){//找到以x为根的最大值 
 87     while(rc[x]!=0) x=rc[x];
 88     return x;
 89 }
 90 int getmin(int x){//找到以x为根的最小值 
 91     while(lc[x]!=0) x=lc[x];
 92     return x;
 93 }
 94 int getpre(int x){//找到节点x的前驱 
 95     splay(x,0);
 96     return getmax(lc[x]);
 97 }
 98 int getne(int x){//找到节点x的后继
 99     splay(x,0);
100     return getmin(rc[x]);
101 }
102 void Delete(int v){//删除一个键值为v的节点 
103     int x=find(v);
104     splay(x,0);
105     int pp=getpre(x),nn=getne(x);
106     splay(pp,0);
107     splay(nn,root);
108     int y=fa[x];
109     fa[x]=0;
110     if(x==lc[y]) lc[y]=0;
111     else lc[x]=0;
112     update(x); update(y);
113 }
114 int rank(int rt,int v){//返回键值为v的节点的排名 
115     if(rt==0) return 1;
116     if(v<=key[rt]) return rank(lc[rt],v);
117     else return siz[lc[rt]]+1+rank(rc[rt],v); 
118 }
119 int findkth(int x,int k){//在以x为根的树中找第 k大 
120     if(siz[lc[x]]+1==k) return key[x];
121     if(siz[lc[x]]+1>k) return findkth(lc[x],k);
122     return findkth(rc[x],k-siz[lc[x]]-1);
123 }
124 
125 int pred(int rt,int v){//返回比 v小的最大的数 
126     if(rt==0) return v;
127     if(v<=key[rt]) return pred(lc[rt],v);
128     else{
129         int ans=pred(rc[rt],v);
130         if(ans==v) return key[rt]; 
131         return ans;
132     }
133 }
134 int succ(int rt,int v){//返回比 v大的最小的数 
135     if(rt==0) return v;
136     if(v>=key[rt]) return succ(rc[rt],v);
137     else{
138         int ans=succ(lc[rt],v);  
139         if(ans==v) return key[rt];
140         return ans;
141     }
142 }
143 int main(){
144     scanf("%d",&T);
145     insert(-50000000); insert(50000000);
146     while (T--){
147         int kin,num;
148         scanf("%d%d",&kin,&num);
149         if(kin==1) insert(num);//插入 
150         else if(kin==2) Delete(num);//删除(若有多个相同的数,只删除一个) 
151         else if(kin==3) printf("%d\n",rank(root,num)-1);//查询num数的排名(若有多个相同的数,因输出最小的排名)
152         else if (kin==4) printf("%d\n",findkth(root,num+1));//查询排名为x的数 
153         else if (kin==5) printf("%d\n",pred(root,num)); 
154         else if (kin==6) printf("%d\n",succ(root,num));
155     }
156     return 0;
157 }

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstdlib>
  4 #include<cmath>
  5 #include<algorithm>
  6 #include<queue>
  7 #include<vector>
  8 using namespace std;
  9 const int maxn=200000;
 10 int key[maxn],lc[maxn],rc[maxn],fa[maxn],siz[maxn];
 11 int tot,root;
 12 int T;
 13 void update(int x){
 14     siz[x]=siz[lc[x]]+1+siz[rc[x]];
 15 }
 16 void r_rotate(int x){
 17     int y=fa[x];
 18     lc[y]=rc[x]; 
 19     if(rc[x]!=0) fa[rc[x]]=y; 
 20     fa[x]=fa[y];
 21     if(y==lc[fa[y]]) lc[fa[y]]=x;
 22     else rc[fa[y]]=x;
 23     fa[y]=x; rc[x]=y;
 24     update(x); update(y);
 25 }
 26 void l_rotate(int x){
 27     int y=fa[x];
 28     rc[y]=lc[x];
 29     if(lc[x]!=0) fa[lc[x]]=y;
 30     fa[x]=fa[y];
 31     if(y==lc[fa[y]]) lc[fa[y]]=x;
 32     else rc[fa[y]]=x;
 33     fa[y]=x; lc[x]=y;
 34     update(x); update(y);
 35 }
 36 void splay(int x,int s){
 37     int p;
 38     while(fa[x]!=s){
 39         p=fa[x];
 40         if(fa[p]==s){
 41             if(x==lc[p]) r_rotate(x);
 42             else l_rotate(x);
 43             break; 
 44         }
 45         if(x==lc[p]){
 46             if(p==lc[fa[p]]) r_rotate(p),r_rotate(x);
 47             else r_rotate(x),l_rotate(x);
 48         }
 49         else{
 50             if(p==rc[fa[p]]) l_rotate(p),l_rotate(x);
 51             else l_rotate(x),r_rotate(x);
 52         }
 53     }
 54     if(s==0) root=x;
 55     update(x);
 56 }
 57 int find(int v){//查找在这棵树中键值为v的节点 
 58     int x=root;
 59     while(x!=0){
 60         if(v<key[x]) x=lc[x];
 61         else if(v>key[x]) x=rc[x];
 62         else if(v==key[x]){
 63             splay(x,0);
 64             return x;
 65         }
 66     }
 67     return -1;
 68 }
 69 void New_node(int &x,int fath,int v){//建立新节点 
 70     x=++tot;
 71     lc[x]=rc[x]=0; siz[x]=1;
 72     fa[x]=fath;
 73     key[x]=v;
 74 }
 75 void insert(int v){//插入新节点 
 76     if(root==0){
 77         New_node(rc[0],0,v);
 78         root=tot;
 79         return ;
 80     }
 81     int p,x=root;
 82     while(x!=0){
 83         p=x;
 84         if(v<=key[x]) siz[x]++,x=lc[x];
 85         else siz[x]++,x=rc[x];
 86     }
 87     if(v<=key[p]) New_node(lc[p],p,v);
 88     else New_node(rc[p],p,v);
 89     splay(tot,0);
 90 }
 91 int getmax(int x){//找到以x为根的最大值 
 92     if(rc[x]!=0) return getmax(rc[x]);
 93     return x;
 94 }
 95 int getmin(int x){//找到以x为根的最小值 
 96        if(lc[x]!=0) return getmin(lc[x]);
 97     return x;
 98 }
 99 int getpre(int x){//找到节点x的前驱 
100     splay(x,0);
101     return getmax(lc[x]);
102 }
103 int getne(int x){//找到节点x的后继
104     splay(x,0);
105     return getmin(rc[x]);
106 }
107 void Delete(int v){
108     int x=find(v);
109     int pp=getmax(lc[x]);
110     int nn=getmin(rc[x]);
111     if(lc[x]==0||rc[x]==0){
112         if(lc[x]==0&&rc[x]==0){
113             root=0; rc[0]=0; 
114             return ;
115         }
116         if(lc[x]==0){
117             rc[0]=rc[x]; fa[rc[x]]=0; root=rc[x]; rc[x]=0;
118             siz[x]=1;
119             return ;
120         }
121         else{
122             rc[0]=lc[x]; fa[lc[x]]=0; root=lc[x]; lc[x]=0;
123             siz[x]=1;
124             return ;
125         }
126     }
127     splay(pp,0);
128     splay(nn,root);
129     fa[lc[nn]]=0; siz[lc[nn]]=1; lc[nn]=0;
130     update(nn); update(pp);
131 } 
132 int rank(int rt,int v){//返回键值为v的节点的排名 
133     if(rt==0) return 1;
134     if(v<=key[rt]) return rank(lc[rt],v);
135     else return siz[lc[rt]]+1+rank(rc[rt],v); 
136 }
137 int findkth(int x,int k){//在以x为根的树中找第 k大 
138     if(siz[lc[x]]+1==k) return key[x];
139     if(siz[lc[x]]+1>k) return findkth(lc[x],k);
140     return findkth(rc[x],k-siz[lc[x]]-1);
141 }
142 
143 int pred(int rt,int v){//返回比 v小的最大的数 
144     if(rt==0)  return v;
145     if(v<=key[rt]) return pred(lc[rt],v);
146     else{
147         int ans=pred(rc[rt],v);
148         if(ans==v) return key[rt]; 
149         return ans;
150     }
151 }
152 int succ(int rt,int v){//返回比 v大的最小的数 
153     if(rt==0) return v;
154     if(v>=key[rt]) return succ(rc[rt],v);
155     else{
156         int ans=succ(lc[rt],v);  
157         if(ans==v) return key[rt];
158         return ans;
159     }
160 }
161 int main(){
162     freopen("phs.in","r",stdin);
163     freopen("phs.out","w",stdout);
164     scanf("%d",&T);
165      while (T--){
166         int kin,num;
167         scanf("%d%d",&kin,&num);
168         if(kin==1) 
169             insert(num);//插入 
170         else if(kin==2) 
171             Delete(num);//删除(若有多个相同的数,只删除一个)
172         else if(kin==3) 
173             printf("%d\n",rank(root,num));//查询num数的排名(若有多个相同的数,因输出最小的排名)
174         else if (kin==4) 
175             printf("%d\n",findkth(root,num));//查询排名为x的数 
176         else if (kin==5) 
177             printf("%d\n",pred(root,num)); 
178         else if (kin==6) 
179             printf("%d\n",succ(root,num));
180     }
181     return 0;
182 }

 

posted @ 2016-02-08 02:52  CXCXCXC  阅读(304)  评论(0编辑  收藏  举报