[BZOJ3196] [Tyvj1730] 二逼平衡树(线段树 套 Splay)

传送门

 

至少BZOJ过了,其他的直接弃。

 

您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:

1.查询k在区间内的排名

2.查询区间内排名为k的值

3.修改某一位值上的数值

4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)

5.查询k在区间内的后继(后继定义为大于x,且最小的数)

 

最外层套一颗线段树,用来表示区间,线段树下面套个splay用来维护当前线段树节点的区间。

对于第二问可以二分,看看哪个数的排名为 k。

 

——代码

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #define root 1, 1, n
  5 #define lson now << 1, l, mid
  6 #define rson now << 1 | 1, mid + 1, r
  7 #define ls son[now][0]
  8 #define rs son[now][1]
  9 #define debug puts("**************");
 10 
 11 const int MAXN = 3500001, INF = 2147483647;
 12 
 13 int n, m, sz;
 14 int seq[MAXN], rt[MAXN];
 15 int f[MAXN], son[MAXN][2], cnt[MAXN], key[MAXN], size[MAXN];
 16 
 17 inline int read()
 18 {
 19     int f = 1, x = 0;
 20     char ch = getchar();
 21     for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
 22     for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
 23     return x * f;
 24 }
 25 
 26 inline int max(int x, int y)
 27 {
 28     return x > y ? x : y;
 29 }
 30 
 31 inline int min(int x, int y)
 32 {
 33     return x < y ? x : y;
 34 }
 35 
 36 inline void Splay_clear(int now)
 37 {
 38     f[now] = cnt[now] = key[now] = size[now] = ls = rs = 0;
 39 }
 40 
 41 inline void Splay_update(int now)
 42 {
 43     if(now)
 44     {
 45         size[now] = cnt[now];
 46         if(ls) size[now] += size[ls];
 47         if(rs) size[now] += size[rs];
 48     }
 49 }
 50 
 51 inline int Splay_get(int x)
 52 {
 53     return son[f[x]][1] == x;
 54 }
 55 
 56 inline void Splay_rotate(int x)
 57 {
 58     int old = f[x], oldf = f[old], wh = Splay_get(x);
 59     
 60     son[old][wh] = son[x][wh ^ 1];
 61     f[son[old][wh]] = old;
 62     
 63     son[x][wh ^ 1] = old;
 64     f[old] = x;
 65     
 66     if(oldf) son[oldf][son[oldf][1] == old] = x;
 67     f[x] = oldf;
 68     
 69     Splay_update(old);
 70     Splay_update(x);
 71 }
 72 
 73 inline void Splay_splay(int x)
 74 {
 75     for(int fa; fa = f[x]; Splay_rotate(x))
 76         if(f[fa])
 77             Splay_rotate(Splay_get(x) ^ Splay_get(fa) ? x : fa);
 78 }
 79 
 80 inline void Splay_insert(int x, int k)
 81 {
 82     int now = rt[x], fa = 0;
 83     if(!rt[x])
 84     {
 85         rt[x] = ++sz;
 86         key[sz] = k;
 87         size[sz] = cnt[sz] = 1;
 88         return;
 89     }
 90     while(1)
 91     {
 92         if(k == key[now])
 93         {
 94             cnt[now]++;
 95             Splay_update(now);
 96             Splay_splay(now);
 97             rt[x] = now;
 98             return;
 99         }
100         fa = now;
101         now = son[now][k > key[now]];
102         if(!now)
103         {
104             rt[x] = ++sz;
105             f[sz] = fa;
106             key[sz] = k;
107             size[sz] = cnt[sz] = 1;
108             son[fa][k > key[fa]] = sz;
109             //Splay_update(fa);
110             Splay_splay(sz);
111             return;
112         }
113     }
114 }
115 
116 inline int Splay_findrank(int x, int k)
117 {
118     int now = rt[x], ans = 0;
119     while(1)
120     {
121         if(!now) return ans;
122         if(key[now] == k) return ans + size[ls];
123         else if(key[now] < k)
124         {
125             ans += cnt[now] + size[ls];
126             now = rs;
127         }
128         else now = ls;
129     }
130 }
131 
132 inline int Splay_find(int x, int k)
133 {
134     int now = rt[x];
135     while(1)
136     {
137         if(key[now] > k) now = ls;
138         else if(key[now] < k) now = rs;
139         else
140         {
141             rt[x] = now;
142             Splay_splay(now);
143             return now;
144         }
145     }
146 }
147 
148 inline int Splay_pre(int x)
149 {
150     int now = son[rt[x]][0];
151     while(rs) now = rs;
152     return now;
153 }
154 
155 inline int Splay_suc(int x)
156 {
157     int now = son[rt[x]][1];
158     while(ls) now = ls;
159     return now;
160 }
161 
162 inline void Splay_del(int x)
163 {
164     int now = rt[x];
165     if(cnt[now] > 1)
166     {
167         cnt[now]--;
168         Splay_update(now);
169         return;
170     }
171     if(!ls && !rs)
172     {
173         rt[x] = 0;
174         Splay_clear(now);
175         return;
176     }
177     if(!ls || !rs)
178     {
179         rt[x] = ls + rs;
180         f[rt[x]] = 0;
181         Splay_clear(now);
182         return;
183     }
184     int pre = Splay_pre(x);
185     Splay_splay(pre);
186     rt[x] = pre;
187     son[pre][1] = rs;
188     f[rs] = pre;
189     Splay_clear(now);
190     Splay_update(pre);
191 }
192 
193 inline int Splay_findpre(int x, int k)
194 {
195     int now = rt[x], ans = -INF;
196     while(now)
197     {
198         if(key[now] < k)
199         {
200             ans = max(ans, key[now]);
201             now = rs;
202         }
203         else now = ls;
204     }
205     return ans;
206 }
207 
208 inline int Splay_findsuc(int x, int k)
209 {
210     int now = rt[x], ans = INF;
211     while(now)
212     {
213         if(key[now] > k)
214         {
215             ans = min(ans, key[now]);
216             now = ls;
217         }
218         else now = rs;
219     }
220     return ans;
221 }
222 
223 inline void SegTree_insert(int x, int k, int now, int l, int r)
224 {
225     Splay_insert(now, k);
226     if(l == r) return;
227     int mid = (l + r) >> 1;
228     if(x <= mid) SegTree_insert(x, k, lson);
229     else SegTree_insert(x, k, rson);
230 }
231 
232 inline int SegTree_askrank(int x, int y, int k, int now, int l, int r)
233 {
234     if(x <= l && r <= y) return Splay_findrank(now, k);
235     if(l > y || r < x) return 0;
236     int mid = (l + r) >> 1;
237     return SegTree_askrank(x, y, k, lson) + SegTree_askrank(x, y, k, rson);
238 }
239 
240 inline void SegTree_change(int x, int k, int now, int l, int r)
241 {
242     Splay_find(now, seq[x]);
243     Splay_del(now);
244     Splay_insert(now, k);
245     if(l == r) return;
246     int mid = (l + r) >> 1;
247     if(x <= mid) SegTree_change(x, k, lson);
248     else SegTree_change(x, k, rson);
249 }
250 
251 inline int SegTree_findpre(int x, int y, int k, int now, int l, int r)
252 {
253     if(x <= l && r <= y) return Splay_findpre(now, k);
254     if(l > y || r < x) return -INF;
255     int mid = (l + r) >> 1;
256     return max(SegTree_findpre(x, y, k, lson), SegTree_findpre(x, y, k, rson));
257 }
258 
259 inline int SegTree_findsuc(int x, int y, int k, int now, int l, int r)
260 {
261     if(x <= l && r <= y) return Splay_findsuc(now, k);
262     if(l > y || r < x) return INF;
263     int mid = (l + r) >> 1;
264     return min(SegTree_findsuc(x, y, k, lson), SegTree_findsuc(x, y, k, rson));
265 }
266 
267 int main()
268 {
269     int i, opt, x, y, z, ans, h, t, mid, maxn = 0;
270     n = read();
271     m = read();
272     for(i = 1; i <= n; i++) seq[i] = read(), maxn = max(maxn, seq[i]), SegTree_insert(i, seq[i], root);
273     for(i = 1; i <= m; i++)
274     {
275         opt = read();
276         switch(opt)
277         {
278             case 1:
279             {
280                 x = read();
281                 y = read();
282                 z = read();
283                 printf("%d\n", SegTree_askrank(x, y, z, root) + 1);
284                 break;
285             }
286             case 2:
287             {
288                 x = read();
289                 y = read();
290                 z = read();
291                 h = 0, t = maxn;
292                 while(h <= t)
293                 {
294                     mid = (h + t) >> 1;
295                     if(SegTree_askrank(x, y, mid, root) + 1 <= z) h = mid + 1;
296                     else ans = mid, t = mid - 1;
297                 }
298                 printf("%d\n", ans - 1);
299                 break;
300             }
301             case 3:
302             {
303                 x = read();
304                 z = read();
305                 SegTree_change(x, z, root);
306                 seq[x] = z;
307                 maxn = max(maxn, z);
308                 break;
309             }
310             case 4:
311             {
312                 x = read();
313                 y = read();
314                 z = read();
315                 printf("%d\n", SegTree_findpre(x, y, z, root));
316                 break;
317             }
318             case 5:
319             {
320                 x = read();
321                 y = read();
322                 z = read();
323                 printf("%d\n", SegTree_findsuc(x, y, z, root));
324                 break;
325             }
326         }
327     }
328     return 0;
329 }
View Code

 

posted @ 2017-05-18 14:56  zht467  阅读(182)  评论(3编辑  收藏  举报