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 }