树套树

TTT(Tree套Tree)

虽然有各种奇怪的套法......先用例题来解释吧。

二逼平衡树。(无数种树套树,还有两种分块,一种整体二分,一种vector的解法...)

题意:给定序列。

1.查询x在[l, r]的排名。

2.查询[l, r]中排名为k的值。

3.修改某个数。

4.查询[l, r]中x的前驱。

5.查询[l, r]中x的后继。

解:解法很多...大致可以通过外层树的类型分成两种:外层值域和外层位置。

内层树又可以选择平衡树或者线段树两种。

外层一般是线段树,也有用树状数组的。

①线段树套平衡树。

最经典的解法,外面是位置线段树,内部是维护权值的平衡树。

首先,可以归并建树。

操作一,对于区间对应的线段树上log个节点,查找比x小的数。答案+1即可。

操作二,在值域上二分,调用操作一判定。

操作三,对于它所在的log个平衡树,全部进行修改。

操作四/五,在区间对应的log个节点上分别查询前驱/后继,取max/min。

实现上可以用结构体封装...

线性建树的时候注意去重,反正我是手写了一个结构体...

注意操作1的x可能不在原序列中。

空间大小,每个节点插入log次,但是我开了哨兵,所以还要多8n的空间。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <queue>
  5 
  6 const int M = 1500010, INF = 2147483647, N = 100010;
  7 
  8 int tot, s[M][2], fa[M], siz[M], cnt[M], val[M];
  9 std::queue<int> Rest;
 10 
 11 struct Node {
 12     int x, y;
 13 }node[N];
 14 
 15 struct Splay {
 16 
 17     int root;
 18 
 19     inline void pushup(int x) {
 20         siz[x] = siz[s[x][0]] + siz[s[x][1]] + cnt[x];
 21         if(!fa[x]) {
 22             root = x;
 23         }
 24         return;
 25     }
 26 
 27     inline void rotate(int x) {
 28         int y = fa[x];
 29         int z = fa[y];
 30         bool f = (s[y][1] == x);
 31 
 32         fa[x] = z;
 33         if(z) {
 34             s[z][s[z][1] == y] = x;
 35         }
 36         s[y][f] = s[x][!f];
 37         if(s[x][!f]) {
 38             fa[s[x][!f]] = y;
 39         }
 40         s[x][!f] = y;
 41         fa[y] = x;
 42 
 43         pushup(y);
 44         pushup(x);
 45         return;
 46     }
 47 
 48     inline void splay(int x, int g = 0) {
 49         int y = fa[x];
 50         int z = fa[y];
 51         while(y != g) {
 52             if(z != g) {
 53                 (s[z][1] == y) ^ (s[y][1] == x) ?
 54                 rotate(x) : rotate(y);
 55             }
 56             rotate(x);
 57             y = fa[x];
 58             z = fa[y];
 59         }
 60         return;
 61     }
 62 
 63     inline int np(int c, int f, int sum = 1) {
 64         int p;
 65         if(Rest.empty()) {
 66             p = ++tot;
 67         }
 68         else {
 69             p = Rest.front();
 70             Rest.pop();
 71         }
 72         fa[p] = f;
 73         s[p][0] = s[p][1] = 0;
 74         siz[p] = cnt[p] = sum;
 75         val[p] = c;
 76         return p;
 77     }
 78 
 79     inline void insert(int c) {
 80         int p = root;
 81         while(1) {
 82             siz[p]++;
 83             if(val[p] == c) {
 84                 cnt[p]++;
 85                 break;
 86             }
 87             if(c < val[p] && s[p][0]) {
 88                 p = s[p][0];
 89             }
 90             else if(val[p] < c && s[p][1]) {
 91                 p = s[p][1];
 92             }
 93             else {
 94                 bool f = (val[p] < c);
 95                 s[p][f] = np(c, p);
 96                 break;
 97             }
 98         }
 99         splay(p);
100         return;
101     }
102 
103     inline int getPbyV(int c) { // if exist return Node else return neighbor
104         int p = root;
105         while(1) {
106             if(val[p] == c) {
107                 break;
108             }
109             else if(c < val[p] && s[p][0]) {
110                 p = s[p][0];
111             }
112             else if(val[p] < c && s[p][1]) {
113                 p = s[p][1];
114             }
115             else {
116                 break;
117             }
118         }
119         return p;
120     }
121 
122     inline int getRP() {
123         int p = s[root][1];
124         while(s[p][0]) {
125             p = s[p][0];
126         }
127         return p;
128     }
129 
130     inline int getLP() {
131         int p = s[root][0];
132         while(s[p][1]) {
133             p = s[p][1];
134         }
135         return p;
136     }
137 
138     inline void del(int c) {
139         int x = getPbyV(c);
140         splay(x);
141         if(cnt[x] > 1) {
142             cnt[x]--;
143             siz[x]--;
144             return;
145         }
146         int y = getRP();
147         splay(y, x);
148         fa[y] = 0;
149         s[y][0] = s[x][0];
150         fa[s[x][0]] = y;
151         pushup(y);
152         Rest.push(x);
153         return;
154     }
155 
156     inline int getPre(int c) {
157         int p = getPbyV(c);
158         splay(p);
159         if(val[p] >= c) {
160             p = getLP();
161             splay(p);
162             return val[p];
163         }
164         else {
165             return val[p];
166         }
167     }
168 
169     inline int getNex(int c) {
170         int p = getPbyV(c);
171         splay(p);
172         if(val[p] <= c) {
173             p = getRP();
174             splay(p);
175             return val[p];
176         }
177         else {
178             return val[p];
179         }
180     }
181 
182     inline int getRbyV(int c) {
183         int p = getPbyV(c);
184         splay(p);
185         if(val[p] < c) {
186             p = getRP();
187             splay(p);
188         }
189         return siz[s[p][0]];
190     }
191 
192     int build(int l, int r, int f) {
193         if(l == r) {
194             return np(node[r].x, f, node[r].y);
195         }
196         int mid = (l + r) >> 1;
197         int p = np(node[mid].x, f, node[mid].y);
198         if(l < mid) {
199             s[p][0] = build(l, mid - 1, p);
200         }
201         if(mid < r) {
202             s[p][1] = build(mid + 1, r, p);
203         }
204         pushup(p);
205         return p;
206     }
207 
208     inline void init(int *a, int n) {
209         int t = 1;
210         node[1].x = a[1];
211         node[1].y = 1;
212         for(int i = 2; i <= n; i++) {
213             if(a[i] != a[i - 1]) {
214                 node[++t].x = a[i];
215                 node[t].y = 0;
216             }
217             node[t].y++;
218         }
219         root = build(1, t, 0);
220         insert(INF);
221         insert(-INF);
222         return;
223     }
224 
225     void out(int x) {
226         if(x == 0) {
227             x = root;
228         }
229         if(s[x][0]) {
230             out(s[x][0]);
231         }
232         for(int i = 1; i <= cnt[x]; i++) {
233             printf("%d ", val[x]);
234         }
235         if(s[x][1]) {
236             out(s[x][1]);
237         }
238         return;
239     }
240     // over
241 }spt[N << 2];
242 
243 int large[N << 2], small[N << 2], a[N], b[N], c[N];
244 
245 inline void pushup(int o) {
246     int ls = o << 1, rs = o << 1 | 1;
247     small[o] = std::min(small[ls], small[rs]);
248     large[o] = std::max(large[ls], large[rs]);
249     return;
250 }
251 
252 int getRank(int L, int R, int v, int l, int r, int o) {
253     if(L <= l && r <= R) {
254         return spt[o].getRbyV(v) - 1;
255     }
256     int mid = (l + r) >> 1, ans = 0;
257     if(L <= mid) {
258         ans += getRank(L, R, v, l, mid, o << 1);
259     }
260     if(mid < R) {
261         ans += getRank(L, R, v, mid + 1, r, o << 1 | 1);
262     }
263     return ans;
264 }
265 
266 int getPre(int L, int R, int v, int l, int r, int o) {
267     if(L <= l && r <= R) {
268         return spt[o].getPre(v);
269     }
270     int ans = -INF, mid = (l + r) >> 1;
271     if(L <= mid) {
272         ans = std::max(ans, getPre(L, R, v, l, mid, o << 1));
273     }
274     if(mid < R) {
275         ans = std::max(ans, getPre(L, R, v, mid + 1, r, o << 1 | 1));
276     }
277     return ans;
278 }
279 
280 int getNex(int L, int R, int v, int l, int r, int o) {
281     if(L <= l && r <= R) {
282         return spt[o].getNex(v);
283     }
284     int mid = (l + r) >> 1, ans = INF;
285     if(L <= mid) {
286         ans = std::min(ans, getNex(L, R, v, l, mid, o << 1));
287     }
288     if(mid < R) {
289         ans = std::min(ans, getNex(L, R, v, mid + 1, r, o << 1 | 1));
290     }
291     return ans;
292 }
293 
294 void change(int p, int v, int l, int r, int o) {
295     spt[o].del(a[p]);
296     spt[o].insert(v);
297     if(l == r) {
298         a[p] = large[o] = small[o] = v;
299         return;
300     }
301     int mid = (l + r) >> 1;
302     if(p <= mid) {
303         change(p, v, l, mid, o << 1);
304     }
305     else {
306         change(p, v, mid + 1, r, o << 1 | 1);
307     }
308     pushup(o);
309     return;
310 }
311 
312 inline void merge(int l, int r) {
313     memcpy(c + l, b + l, (r - l + 1) * sizeof(int));
314     int mid = (l + r) >> 1;
315     int i = l, j = mid + 1, t = l;
316     while(t <= r) {
317         if(j > r || (i <= mid && c[i] < c[j])) {
318             b[t++] = c[i];
319             i++;
320         }
321         else {
322             b[t++] = c[j];
323             j++;
324         }
325     }
326     return;
327 }
328 
329 void build(int l, int r, int o) {
330     if(l == r) {
331         spt[o].init(b + r - 1, 1);
332         small[o] = large[o] = b[r];
333         return;
334     }
335     int mid = (l + r) >> 1;
336     build(l, mid, o << 1);
337     build(mid + 1, r, o << 1 | 1);
338     merge(l, r);
339     spt[o].init(b + l - 1, r - l + 1);
340     pushup(o);
341     return;
342 }
343 
344 int getMax(int L, int R, int l, int r, int o) {
345     if(L <= l && r <= R) {
346         return large[o];
347     }
348     int mid = (l + r) >> 1, ans = -INF;
349     if(L <= mid) {
350         ans = std::max(ans, getMax(L, R, l, mid, o << 1));
351     }
352     if(mid < R) {
353         ans = std::max(ans, getMax(L, R, mid + 1, r, o << 1 | 1));
354     }
355     return ans;
356 }
357 
358 int getMin(int L, int R, int l, int r, int o) {
359     if(L <= l && r <= R) {
360         return small[o];
361     }
362     int mid = (l + r) >> 1, ans = INF;
363     if(L <= mid) {
364         ans = std::min(ans, getMin(L, R, l, mid, o << 1));
365     }
366     if(mid < R) {
367         ans = std::min(ans, getMin(L, R, mid + 1, r, o << 1 | 1));
368     }
369     return ans;
370 }
371 
372 void out(int l, int r, int o) {
373     printf("out %d %d : ", l, r);
374     spt[o].out(0);
375     puts("");
376     if(l == r) {
377         return;
378     }
379     int mid = (l + r) >> 1;
380     out(l, mid, o << 1);
381     out(mid + 1, r, o << 1 | 1);
382     return;
383 }
384 
385 int main() {
386 
387     int n, m;
388     scanf("%d%d", &n, &m);
389     for(int i = 1; i <= n; i++) {
390         scanf("%d", &a[i]);
391         b[i] = a[i];
392     }
393     build(1, n, 1);
394 
395     for(int i = 1, x, y, z, f; i <= m; i++) {
396         scanf("%d%d%d", &f, &x, &y);
397         if(f == 1) {
398             scanf("%d", &z);
399             int t = getRank(x, y, z, 1, n, 1);
400             printf("%d\n", t + 1);
401         }
402         else if(f == 2) {
403             scanf("%d", &z);
404             int l = getMin(x, y, 1, n, 1), r = getMax(x, y, 1, n, 1);
405             while(l < r) {
406                 int mid = (l + r + 1) >> 1;
407                 if(getRank(x, y, mid, 1, n, 1) + 1 <= z) {
408                     l = mid;
409                 }
410                 else {
411                     r = mid - 1;
412                 }
413             }
414             printf("%d\n", r);
415         }
416         else if(f == 3) {
417             change(x, y, 1, n, 1);
418         }
419         else if(f == 4) {
420             scanf("%d", &z);
421             int t = getPre(x, y, z, 1, n, 1);
422             printf("%d\n", t);
423         }
424         else if(f == 5) {
425             scanf("%d", &z);
426             int t = getNex(x, y, z, 1, n, 1);
427             printf("%d\n", t);
428         }
429     }
430 
431     return 0;
432 }
AC代码

洛谷上卡时1961ms过了,不开O(2)是信仰。然而石室老爷机T了两个点...

别的做法懒得写了。

搞点例题来吧。因为带修主席树的本质是树套树所以也会放在这里。

网络管理  任务查询系统  Dynamic Rankings 

posted @ 2019-01-17 09:19  huyufeifei  阅读(...)  评论(...编辑  收藏