码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ3196二逼平衡树【树套树】

时间:2017-05-25 20:48:56      阅读:305      评论:0      收藏:0      [点我收藏+]

标签:and   结构   php   use   scan   nbsp   style   input   需要   

3196: Tyvj 1730 二逼平衡树

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 3776  Solved: 1483

Description

您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:
1.查询k在区间内的排名
2.查询区间内排名为k的值
3.修改某一位值上的数值
4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)
5.查询k在区间内的后继(后继定义为大于x,且最小的数)

Input

第一行两个数 n,m 表示长度为n的有序序列和m个操作
第二行有n个数,表示有序序列
下面有m行,opt表示操作标号
若opt=1 则为操作1,之后有三个数l,r,k 表示查询k在区间[l,r]的排名
若opt=2 则为操作2,之后有三个数l,r,k 表示查询区间[l,r]内排名为k的数
若opt=3 则为操作3,之后有两个数pos,k 表示将pos位置的数修改为k
若opt=4 则为操作4,之后有三个数l,r,k 表示查询区间[l,r]内k的前驱
若opt=5 则为操作5,之后有三个数l,r,k 表示查询区间[l,r]内k的后继

Output

对于操作1,2,4,5各输出一行,表示查询结果

Sample Input

9 6
4 2 2 1 9 4 0 1 1
2 1 4 3
3 4 10
2 1 4 3
1 2 5 9
4 3 9 5
5 2 8 5

Sample Output

2
4
3
4
9

HINT

1.n和m的数据范围:n,m<=50000

2.序列中每个数的数据范围:[0,1e8]

3.虽然原题没有,但事实上5操作的k可能为负数
 
Q and A
Q:这题怎么搞?
A:外层线段树。。。内层平衡树。。。
Q:真哒?我怎么A不了?
A:这,要拼命水。
Q:那。。。怎么水呢?
A:xjb乱水,O3。。。读入优化。。。各种卡常数。。。卡过10s算数。
Q:那么我怎么看见有人2000ms过了呢?
A:因为正解是整体二分啊,那是大佬专用的神级存在,我辈就不要凑热闹了。

1.外层线段树既然使用root数组,就应当开到区间大小的3倍以上!!!
2.BST中找一个节点的前驱、后继、排名,可以从根按照key相对于x的位置一路找下来得到解.
3.读入优化收效甚微但是刚好够我卡过去.

2080186 The_Unbeatable 3196 Accepted 51704 kb 9760 ms C++/Edit 6430 B 2017-05-25 19:06:26
  1 %:pragma GCC optimize(3)
  2 #include<cstdio>
  3 #include<queue>
  4 #include<iostream>
  5 using namespace std;
  6 const int N=50005;
  7 const int M=2100001;
  8 const int INF=1e8+5;
  9 int n,root[N*5],lch[M],rch[M],size[M],key[M],fa[M],rep[M],S=1,rec[N];
 10 queue<int> Q;
 11 inline void Discard(int x)
 12 {
 13     lch[x]=rch[x]=key[x]=rep[x]=size[x]=fa[x]=0;
 14     if(x) Q.push(x);
 15 }
 16 inline int newnode()
 17 {
 18     if(!Q.empty())
 19     {
 20         int ret=Q.front();
 21         Q.pop();
 22         return ret;
 23     }
 24     return ++S;
 25 }
 26 inline void update(int p) {size[p]=rep[p]+size[lch[p]]+size[rch[p]];}
 27 inline void zig(int x)
 28 {
 29     int f=fa[x],gf=fa[f];
 30     fa[f]=x;
 31     fa[x]=gf;
 32     if(gf)
 33     {
 34         if(lch[gf]==f) lch[gf]=x;
 35         else rch[gf]=x;
 36     }
 37     lch[f]=rch[x];
 38     if(rch[x]) fa[rch[x]]=f;
 39     rch[x]=f;
 40     update(f);
 41     update(x);
 42 }
 43 inline void zag(int x)
 44 {
 45     int f=fa[x],gf=fa[f];
 46     fa[f]=x;
 47     fa[x]=gf;
 48     if(gf)
 49     {
 50         if(lch[gf]==f) lch[gf]=x;
 51         else rch[gf]=x;
 52     }
 53     rch[f]=lch[x];
 54     if(lch[x]) fa[lch[x]]=f;
 55     lch[x]=f;
 56     update(f);
 57     update(x);
 58 }
 59 inline void Splay(int x,int T)
 60 {
 61     int f,gf;
 62     while(fa[x]!=T)
 63     {
 64         f=fa[x];
 65         gf=fa[f];
 66         if(gf==T)
 67         {
 68             if(x==lch[f]) zig(x);
 69             else zag(x);
 70             break;
 71         }
 72         if(f==lch[gf])
 73         {
 74             if(x==lch[f]) {zig(f);zig(x);}
 75             else {zag(x);zig(x);}
 76         }
 77         else
 78         {
 79             if(x==lch[f]) {zig(x);zag(x);}
 80             else {zag(f);zag(x);}
 81         }
 82     }
 83 }
 84 inline int Inner_Find(int x,int p)
 85 {
 86     while(key[p]!=x)
 87     {
 88         if(x<key[p])
 89         {
 90             if(!lch[p]) break;
 91             p=lch[p];
 92         }
 93         else
 94         {
 95             if(!rch[p]) break;
 96             p=rch[p];
 97         }
 98     }
 99     return p;
100 }
101 inline void Inner_Insert(int x,int T)
102 {
103     if(!root[T])
104     {
105         root[T]=newnode();
106         key[root[T]]=x;
107         size[root[T]]=rep[root[T]]=1;
108         return;
109     }
110     int k=Inner_Find(x,root[T]);
111     if(x==key[k])
112     {
113         rep[k]++;
114         size[k]++;
115     }
116     else if(x<key[k])
117     {
118         lch[k]=newnode();
119         fa[lch[k]]=k;
120         k=lch[k];
121         size[k]=rep[k]=1;
122         key[k]=x;
123     }
124     else
125     {
126         rch[k]=newnode();
127         fa[rch[k]]=k;
128         k=rch[k];
129         size[k]=rep[k]=1;
130         key[k]=x;
131     }
132     Splay(k,0);
133     root[T]=k;
134 }
135 inline int Find_Max(int p)
136 {
137     while(rch[p]) p=rch[p];
138     return p;
139 }
140 inline void Inner_Delete(int x,int T,bool rot)
141 {
142     int k;
143     if(!rot) k=Inner_Find(x,root[T]);
144     else k=root[T];
145     if(rep[k]>1)
146     {
147         rep[k]--;
148         update(k);
149         update(fa[k]);
150         Splay(k,0);
151         root[T]=k;
152         return;
153     }
154     Splay(k,0);
155     root[T]=k;
156     if(lch[k])
157     {
158         if(rch[k])
159         {
160             int u=Find_Max(lch[k]);
161             Splay(u,root[T]);
162             root[T]=lch[k];
163             fa[lch[k]]=0;
164             rch[lch[k]]=rch[k];
165             fa[rch[k]]=lch[k];
166         }
167         else
168         {
169             root[T]=lch[k];
170             fa[lch[k]]=0;
171         }
172     }
173     else if(rch[k])
174     {
175         root[T]=rch[k];
176         fa[rch[k]]=0;
177     }
178     else root[T]=0;
179     Discard(k);
180     if(root[T]) update(root[T]);
181 }
182 inline void Outer_Insert(int pos,int x)
183 {
184     int l=1,r=n,p=1,mid;
185     while(l<r)
186     {
187         Inner_Insert(x,p);
188         mid=(l+r)>>1;
189         if(pos<=mid) {r=mid;p<<=1;}
190         else {l=mid+1;p=(p<<1)+1;}
191     }
192     Inner_Insert(x,p);
193 }
194 inline void Outer_Delete(int pos,int x)
195 {
196     int l=1,r=n,p=1,mid;
197     while(l<r)
198     {
199         Inner_Delete(x,p,0);
200         mid=(l+r)>>1;
201         if(pos<=mid) {r=mid;p<<=1;}
202         else {l=mid+1;p=(p<<1)+1;}
203     }
204     Inner_Delete(x,p,0);
205 }
206 inline int Inner_Rank(int T,int x)
207 {
208     int p=root[T],res=0;
209     while(1)
210     {
211         if(!p) return res;
212         if(key[p]==x) return res+size[lch[p]];
213         if(key[p]<x)
214         {
215             res+=size[lch[p]]+rep[p];
216             p=rch[p];
217         }
218         else p=lch[p];
219     }
220     return res;
221 }
222 inline int Query_Rank(int T,int l,int r,int a,int b,int k)
223 {
224     if(l==a&&r==b) return Inner_Rank(T,k);
225     if(l==r) return 0;
226     int mid=(l+r)>>1;
227     if(b<=mid) return Query_Rank(T*2,l,mid,a,b,k);
228     else if(a>mid) return Query_Rank(T*2+1,mid+1,r,a,b,k);
229     else return Query_Rank(T*2,l,mid,a,mid,k)+Query_Rank(T*2+1,mid+1,r,mid+1,b,k);
230 }
231 inline int Inner_Pre(int T,int x)
232 {
233     int p=root[T],res=-INF;
234     while(p)
235     {
236         if(key[p]<x)
237         {
238             res=max(res,key[p]);
239             p=rch[p];
240         }
241         else p=lch[p];
242     }
243     return res;
244 }
245 inline int Query_Pre(int T,int l,int r,int a,int b,int k)
246 {
247     if(l==a&&r==b) return Inner_Pre(T,k);
248     int mid=(l+r)>>1;
249     if(b<=mid) return Query_Pre(T*2,l,mid,a,b,k);
250     else if(a>mid) return Query_Pre(T*2+1,mid+1,r,a,b,k);
251     else return max(Query_Pre(T*2,l,mid,a,mid,k),Query_Pre(T*2+1,mid+1,r,mid+1,b,k));
252 }
253 inline int Inner_Next(int T,int x)
254 {
255     int p=root[T],res=INF;
256     while(p)
257     {
258         if(key[p]>x)
259         {
260             res=min(res,key[p]);
261             p=lch[p];
262         }
263         else p=rch[p];
264     }
265     return res;
266 }
267 inline int Query_Next(int T,int l,int r,int a,int b,int k)
268 {
269     if(l==a&&r==b) return Inner_Next(T,k);
270     int mid=(l+r)>>1;
271     if(b<=mid) return Query_Next(T*2,l,mid,a,b,k);
272     else if(a>mid) return Query_Next(T*2+1,mid+1,r,a,b,k);
273     else return min(Query_Next(T*2,l,mid,a,mid,k),Query_Next(T*2+1,mid+1,r,mid+1,b,k));
274 }
275 inline int Query_Kth(int a,int b,int k)
276 {
277     int l=1,r=INF,mid,res,c;
278     while(l<=r)
279     {
280         mid=(l+r)>>1;
281         c=Query_Rank(1,1,n,a,b,mid)+1;
282         if(c<=k){l=mid+1;res=mid;}
283         else r=mid-1;
284     }
285     return res;
286 }
287 inline int read(int &u)
288 {
289     int f=1,x=0;
290     char ch=getchar();
291     for(;!isdigit(ch);ch=getchar()) if(ch==-) f=-1;
292     for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+ch-0;
293     u=x*f;
294 }
295 int main()
296 {
297     int m,opt,k,a,b;
298     read(n);
299     read(m);
300     for(int i=1;i<=n;i++)
301     {
302         read(rec[i]);
303         Outer_Insert(i,rec[i]);
304     }
305     while(m--)
306     {
307         scanf("%d",&opt);
308         if(opt==3) read(a),read(k);
309         else read(a),read(b),read(k);
310         switch(opt)
311         {
312             case 1:
313                 printf("%d\n",Query_Rank(1,1,n,a,b,k)+1);
314                 break;
315             case 2:
316                 printf("%d\n",Query_Kth(a,b,k));
317                 break;
318             case 3:
319                 Outer_Insert(a,k);
320                 Outer_Delete(a,rec[a]);
321                 rec[a]=k;
322                 break;
323             case 4:
324                 printf("%d\n",Query_Pre(1,1,n,a,b,k));
325                 break;
326             case 5:
327                 printf("%d\n",Query_Next(1,1,n,a,b,k));
328                 break;
329         }
330     }
331     return 0;
332 }

 

BZOJ3196二逼平衡树【树套树】

标签:and   结构   php   use   scan   nbsp   style   input   需要   

原文地址:http://www.cnblogs.com/the-unbeatable/p/6905531.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!