[洛谷P3369] 普通平衡树 Treap & Splay
这个就是存一下板子......
Treap的实现应该是比较正经的。
插入删除前驱后继排名什么的都是平衡树的基本操作。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdlib> 5 using namespace std; 6 7 int n,root,tot; 8 9 struct treap 10 { 11 int ls,rs,v,rd,sz,h; 12 }t[100005]; 13 14 void update(int p) 15 { 16 t[p].sz=t[t[p].ls].sz+t[t[p].rs].sz+t[p].h; 17 } 18 19 void zig(int &p) 20 { 21 int r=t[p].rs; 22 t[p].rs=t[r].ls; 23 t[r].ls=p; 24 t[r].sz=t[p].sz; 25 update(p); 26 p=r; 27 } 28 29 void zag(int &p) 30 { 31 int l=t[p].ls; 32 t[p].ls=t[l].rs; 33 t[l].rs=p; 34 t[l].sz=t[p].sz; 35 update(p); 36 p=l; 37 } 38 39 void insert(int &p,int val) 40 { 41 if(p==0) 42 { 43 tot++; 44 p=tot; 45 t[p].sz=t[p].h=1; 46 t[p].v=val; 47 t[p].rd=rand(); 48 return; 49 } 50 t[p].sz++; 51 if(t[p].v==val)t[p].h++; 52 else if(t[p].v<val) 53 { 54 insert(t[p].rs,val); 55 if(t[p].rd>t[t[p].rs].rd)zig(p); 56 }else 57 { 58 insert(t[p].ls,val); 59 if(t[p].rd>t[t[p].ls].rd)zag(p); 60 } 61 } 62 63 void del(int &p,int val) 64 { 65 if(!p)return; 66 if(t[p].v==val) 67 { 68 if(t[p].h>1) 69 { 70 t[p].h--; 71 t[p].sz--; 72 return; 73 } 74 if(t[p].ls*t[p].rs==0)p=t[p].ls+t[p].rs; 75 else if(t[t[p].ls].rd<t[t[p].rs].rd) 76 { 77 zag(p); 78 del(p,val); 79 }else 80 { 81 zig(p); 82 del(p,val); 83 } 84 }else if(t[p].v<val) 85 { 86 t[p].sz--; 87 del(t[p].rs,val); 88 }else 89 { 90 t[p].sz--; 91 del(t[p].ls,val); 92 } 93 } 94 95 int qrank(int p,int val) 96 { 97 if(!p)return 0; 98 if(t[p].v==val)return t[t[p].ls].sz+1; 99 else if(t[p].v<val)return t[t[p].ls].sz+t[p].h+qrank(t[p].rs,val); 100 else return qrank(t[p].ls,val); 101 } 102 103 int qnum(int p,int rk) 104 { 105 if(!p)return 0; 106 int lsz=t[t[p].ls].sz+t[p].h; 107 if(rk<=t[t[p].ls].sz)return qnum(t[p].ls,rk); 108 else if(rk>lsz)return qnum(t[p].rs,rk-lsz); 109 else return t[p].v; 110 } 111 112 void pre(int p,int val,int &ans) 113 { 114 if(!p)return; 115 if(t[p].v<val) 116 { 117 ans=p; 118 pre(t[p].rs,val,ans); 119 }else pre(t[p].ls,val,ans); 120 } 121 122 void post(int p,int val,int &ans) 123 { 124 if(!p)return; 125 if(t[p].v>val) 126 { 127 ans=p; 128 post(t[p].ls,val,ans); 129 }else post(t[p].rs,val,ans); 130 } 131 132 int main() 133 { 134 scanf("%d",&n); 135 int op,x; 136 while(n--) 137 { 138 scanf("%d%d",&op,&x); 139 if(op==1)insert(root,x); 140 if(op==2)del(root,x); 141 if(op==3)printf("%d\n",qrank(root,x)); 142 if(op==4)printf("%d\n",qnum(root,x)); 143 if(op==5){int r=0;pre(root,x,r);printf("%d\n",t[r].v);} 144 if(op==6){int r=0;post(root,x,r);printf("%d\n",t[r].v);} 145 } 146 return 0; 147 }
今天突然想用splay写一下,复习复习。
之后发现第12个点T飞了......
下载输入数据之后,发现这个数据是构造的,依次插入了1~50000这50000个数。
用cfree调试了一下,发现这样会在splay上弄出一个长长的链。
可能是我太菜了,但是我用了两种方法(具体见代码)都会出链导致T飞。
最后为了男人的尊严,我用了一些玄学(随机)算法总算A掉了。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdlib> 5 #define id(x) (s[f[x]][1]==x) 6 using namespace std; 7 8 int n,root=2,tot=2; 9 int f[100005],s[100005][2]; 10 int v[100005],h[100005],sz[100005]; 11 12 void pushup(int p) 13 { 14 sz[p]=sz[s[p][0]]+sz[s[p][1]]+h[p]; 15 } 16 17 void rotate(int p) 18 { 19 int k=id(p); 20 int fa=f[p]; 21 s[fa][k]=s[p][!k]; 22 s[p][!k]=fa; 23 s[f[fa]][id(fa)]=p; 24 f[p]=f[fa]; 25 f[fa]=p; 26 f[s[fa][k]]=fa; 27 pushup(fa); 28 pushup(p); 29 } 30 31 void splay(int p,int g) 32 { 33 while(f[p]!=g) 34 { 35 int fa=f[p]; 36 if(f[fa]==g) 37 { 38 rotate(p); 39 break; 40 } 41 if(id(p)^id(fa))rotate(p); 42 else rotate(fa); 43 rotate(p); 44 } 45 if(!g)root=p; 46 } 47 48 void pre(int p,int val,int &ans) 49 { 50 if(!p)return; 51 if(v[p]>=val)pre(s[p][0],val,ans); 52 else ans=p,pre(s[p][1],val,ans); 53 } 54 55 void post(int p,int val,int &ans) 56 { 57 if(!p)return; 58 if(v[p]<=val)post(s[p][1],val,ans); 59 else ans=p,post(s[p][0],val,ans); 60 } 61 62 int qrank(int p,int num) 63 { 64 if(!p)return 0; 65 if(num<v[p])return qrank(s[p][0],num); 66 if(num==v[p])return sz[s[p][0]]+1; 67 return sz[s[p][0]]+h[p]+qrank(s[p][1],num); 68 } 69 70 int qnum(int p,int rk) 71 { 72 if(!p)return 0; 73 int lm=sz[s[p][0]]+h[p]; 74 if(rk<=sz[s[p][0]])return qnum(s[p][0],rk); 75 if(rk>lm)return qnum(s[p][1],rk-lm); 76 return v[p]; 77 } 78 79 int d[100005]; 80 81 void ins(int val) 82 { 83 /*int bef,aft; 84 pre(root,val,bef); 85 post(root,val,aft); 86 splay(bef,0); 87 splay(aft,root); 88 int gp=s[root][1]; 89 if(!s[gp][0]) 90 { 91 s[gp][0]=++tot; 92 f[tot]=gp; 93 v[tot]=val; 94 } 95 h[s[gp][0]]++,sz[s[gp][0]]++; 96 pushup(gp),pushup(root);*/ 97 98 int p=root,fa=0; 99 while(p&&v[p]!=val) 100 { 101 fa=p; 102 p=s[p][val>v[p]]; 103 } 104 if(!p) 105 { 106 p=++tot; 107 s[fa][val>v[fa]]=p; 108 sz[p]=1; 109 f[p]=fa; 110 v[p]=val; 111 } 112 h[p]++; 113 splay(p,0); 114 int k=rand()%tot+1; 115 while(d[k])k=rand()%tot+1; 116 splay(k,0); 117 } 118 119 void del(int val) 120 { 121 int bef,aft; 122 pre(root,val,bef); 123 post(root,val,aft); 124 splay(bef,0); 125 splay(aft,root); 126 int gp=s[root][1]; 127 h[s[gp][0]]--; 128 sz[s[gp][0]]--; 129 if(!h[s[gp][0]])d[s[gp][0]]=1,s[gp][0]=0; 130 pushup(gp),pushup(root); 131 } 132 133 int main() 134 { 135 scanf("%d",&n); 136 f[1]=2; 137 s[2][0]=1; 138 v[1]=-0x3f3f3f3f; 139 v[2]=0x3f3f3f3f; 140 h[1]=h[2]=sz[1]=1; 141 sz[2]=2; 142 for(int i=1;i<=n;i++) 143 { 144 int op,x; 145 scanf("%d%d",&op,&x); 146 if(op==1)ins(x); 147 if(op==2)del(x); 148 if(op==3){int rk=qrank(root,x)-1;printf("%d\n",rk);} 149 if(op==4){int num=qnum(root,x+1);printf("%d\n",num);} 150 if(op==5){int pos;pre(root,x,pos);printf("%d\n",v[pos]);} 151 if(op==6){int pos;post(root,x,pos);printf("%d\n",v[pos]);} 152 } 153 return 0; 154 }