替罪羊树模板(题目:普通平衡树)

Posted scx2015noip-as-php

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了替罪羊树模板(题目:普通平衡树)相关的知识,希望对你有一定的参考价值。

我要喷写这题题解的人,害得我调错了 $n$ 多个小时!!

 

技术分享图片
  1 #include<bits/stdc++.h>
  2 #define lc tr[o].l
  3 #define rc tr[o].r
  4 #define N 100001
  5 #define inf 2147483647
  6 const double alpha=0.7;
  7 using namespace std;
  8 inline int read(){
  9     int x=0; bool f=1; char c=getchar();
 10     while(!isdigit(c)){if(c==-) f=0; c=getchar();}
 11     while(isdigit(c)){x=(x<<3)+(x<<1)+c-0; c=getchar();}
 12     if(!f) return 0-x;
 13     return x;
 14 }
 15 int n,root,op,x,cnt;
 16 int v[N];
 17 int bad,fa;
 18 bool exist,son;
 19 namespace ForceTree{
 20     struct node{
 21         int l,r,val,siz,cnt;
 22         bool deleted;
 23     }tr[N<<2];
 24     vector<int>v;
 25     inline bool isbad(int o){
 26         //cout<<tr[lc].cnt<<‘ ‘<<tr[rc].cnt<<‘ ‘<<alpha*tr[o].cnt+5<<‘ ‘<<(tr[lc].cnt>alpha*tr[o].cnt+5)<<‘ ‘<<(tr[rc].cnt>alpha*tr[o].cnt+5)<<‘
‘;
 27         return tr[lc].cnt>alpha*tr[o].cnt+5 || tr[rc].cnt>alpha*tr[o].cnt+5;
 28     }
 29     inline void pushup(int o){
 30         tr[o].siz = (!tr[o].deleted && tr[o].val!=inf && tr[o].val!=-inf)+tr[lc].siz+tr[rc].siz;
 31         tr[o].cnt = 1+tr[lc].cnt+tr[rc].cnt;
 32     }
 33     void dfs(int o){
 34         if(lc) dfs(lc);
 35         if(!tr[o].deleted) v.push_back(o);
 36         if(rc) dfs(rc);
 37     }
 38     void build(int &o,int l,int r){
 39         if(l>=r){o=0; return;} //o=0,注意!不然某个叶子结点的儿子可能没刷掉! 
 40         int mid=(l+r)>>1;
 41         o=v[mid];
 42         //printf("build:%d %d %d %d
",o,tr[o].val,l,r);
 43         build(lc,l,mid), build(rc,mid+1,r);
 44         pushup(o);
 45     }
 46     void rebuild(int &o){
 47         //printf("rebuild
");
 48         v.clear();
 49         dfs(o);
 50         build(o,0,v.size());
 51     }
 52     void insert(int &o,int x){
 53         if(!o){
 54             o=++cnt;
 55             lc=rc=0;
 56             tr[o].deleted=0;
 57             if(x==-inf || x==inf) tr[o].siz=0;
 58             else tr[o].siz=1;
 59             tr[o].cnt=1;
 60             tr[o].val=x;
 61             return;
 62         }
 63         else{
 64             if(x!=-inf && x!=inf) ++tr[o].siz;
 65             ++tr[o].cnt;
 66             if(x<tr[o].val){
 67                 insert(lc,x);
 68                 if(bad==lc) fa=o, son=0; //bad点的父亲到后面要更新儿子 
 69             }
 70             else{
 71                 insert(rc,x);
 72                 if(bad==rc) fa=o, son=1;
 73             }
 74             if(isbad(o)) bad=o; //优化? 
 75         }
 76     }
 77     int rank(int o,int x){
 78         int ans=1;
 79         while(o){
 80             //printf("%d %d %d
",tr[o].val,tr[o].siz,tr[lc].siz);
 81             if(x<=tr[o].val){
 82                 if(x==tr[o].val) exist=1;
 83                 o=lc;
 84             }
 85             else{
 86                 //printf("%d %d
",tr[lc].siz,(tr[o].val!=-inf && tr[o].val!=inf && !tr[o].deleted));
 87                 ans+=tr[lc].siz+(tr[o].val!=-inf && tr[o].val!=inf && !tr[o].deleted);
 88                 o=rc;
 89             }
 90         }
 91         return ans;
 92     }
 93     int kth(int o,int x){
 94         //printf("rank:%d
",x);
 95         if(x<=0) return -inf;
 96         while(o){
 97             //printf("%d %d
",tr[o].val,tr[lc].siz);
 98             if(!tr[o].deleted && tr[o].val!=inf && tr[o].val!=-inf && tr[lc].siz+1==x) return tr[o].val;
 99             if(x<=tr[lc].siz) o=lc;
100             else{
101                 x-=tr[lc].siz+(tr[o].val!=-inf && tr[o].val!=inf && !tr[o].deleted);
102                 o=rc;
103             }
104         }
105         return inf;
106     }
107     void erase(int o,int rk){
108         if(!exist) return;
109         while(o){
110             if(!tr[o].deleted && tr[o].val!=inf && tr[o].val!=-inf && tr[lc].siz+1==rk){
111                 //printf("erase:%d %d
",tr[o].val,x);
112                 if(tr[o].val==x) tr[o].deleted=1, --tr[o].siz;
113                 return;
114             }
115             --tr[o].siz;
116             if(rk<=tr[lc].siz) o=lc;
117             else{
118                 rk-=tr[lc].siz+(tr[o].val!=-inf && tr[o].val!=inf && !tr[o].deleted);
119                 o=rc;
120             }
121         }
122     }
123 };
124 using namespace ForceTree;
125 int main(){
126     //freopen("rand.in","r",stdin);
127     //freopen("count.out","w",stdout);
128     n=read();
129     insert(root,-2147483647), insert(root,2147483647);
130     while(n--){
131         op=read(),x=read();
132         if(op==1){
133             bad=-1;
134             insert(root,x);
135             if(bad!=-1){
136                 //printf("bad:%d %d %d %d
",root,fa,bad,tr[bad].val);
137                 if(bad==root) rebuild(bad), root=bad; //注意!! 
138                 else{
139                     rebuild(bad);
140                     if(!son) tr[fa].l=bad;
141                     else tr[fa].r=bad;
142                 }
143             }
144         }
145         if(op==2){
146             exist=0;
147             erase(root,rank(root,x));
148         }
149         if(op==3) printf("%d
",rank(root,x));
150         if(op==4) printf("%d
",kth(root,x));
151         if(op==5) printf("%d
",kth(root,rank(root,x)-1));
152         if(op==6) printf("%d
",kth(root,rank(root,x+1)));
153     }
154     return 0;
155 }
156 /*
157 3
158 1 87
159 1 68
160 3 50
161 
162 45
163 1 914241
164 1 639471
165 5 917713
166 6 912745
167 1 234811
168 1 297728
169 3 297728
170 1 6927
171 5 645391
172 1 664569
173 2 914241
174 1 134689
175 1 868271
176 1 842266
177 5 850426
178 1 286545
179 4 1
180 1 333833
181 1 274177
182 1 568845
183 1 157569
184 4 13
185 1 732493
186 4 7
187 4 9
188 5 646117
189 1 136381
190 1 473089
191 1 419305
192 1 639776
193 3 473089
194 4 7
195 6 234571
196 1 37685
197 1 321207
198 1 496713
199 1 531105
200 2 234811
201 2 157569
202 1 326601
203 1 317437
204 1 791873
205 1 931097
206 1 224521
207 3 317437
208 
209 50
210 1 1
211 1 2
212 1 3
213 1 4
214 1 5
215 1 6
216 1 7
217 1 8
218 1 9
219 1 10
220 1 11
221 1 12
222 1 13
223 1 14
224 1 15
225 1 16
226 1 17
227 1 18
228 1 19
229 1 20
230 1 21
231 1 22
232 1 23
233 1 24
234 
235 5
236 1 1
237 1 5
238 2 5
239 3 4
240 */
View Code

 

以上是关于替罪羊树模板(题目:普通平衡树)的主要内容,如果未能解决你的问题,请参考以下文章

[luogu3369]普通平衡树(替罪羊树模板)

[TYVJ1728/BZOJ3224]普通平衡树-替罪羊树

模板替罪羊树

替罪羊树模版 普通平衡树

对于各种各样平衡树的比较

BZOJ3224_普通平衡树_KEY