1. 程式人生 > >[洛谷P3369] 普通平衡樹 Treap & Splay

[洛谷P3369] 普通平衡樹 Treap & Splay

mes href using oid org 題目 scanf printf std

這個就是存一下板子......

題目傳送門

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 }

[洛谷P3369] 普通平衡樹 Treap & Splay