洛谷P3391 文艺平衡树 (Splay模板)

模板题。

打区间翻转标记,要翻转区间[l, r] ,需要将l - 1翻转到根,再将r + 1翻转至根节点的儿子,因此要设立首尾哨兵。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 1e5 + 10, inf = 1e9 + 10;
 4 int lc[N], rc[N], fa[N], sze[N], vi[N], pos[N], a[N];
 5 int n, m, rt, T, x, y;
 6 inline int read() {
 7     int x = 0, f = 1; char ch = getchar();
 8     while (ch < '0' || ch > '9') {if (ch == '-') f = -1; ch = getchar();}
 9     while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
10     return x * f;
11 }
12 namespace Splay {
13     void pushup(int x) {
14         sze[x] = sze[lc[x]] + sze[rc[x]] + 1;
15     }
16     int build(int lst, int l, int r) {
17         if (l > r) return 0;
18         int mid = (l + r) >> 1, x = ++ T;
19         fa[x] = lst; pos[x] = 0; vi[x] = a[mid];
20         lc[x] = build(x, l, mid - 1);
21         rc[x] = build(x, mid + 1, r);
22         pushup(x);
23         return x;
24     }
25     void pushdown(int x) {//下传翻转标记 
26         if (x && pos[x]) {
27             pos[lc[x]] ^= 1;
28             pos[rc[x]] ^= 1;
29             swap(lc[x], rc[x]);
30             pos[x] = 0;
31         }
32     }
33     bool Wrt(int x) {
34         return rc[fa[x]] == x;
35     }
36     void rot(int x) {
37         int y = fa[x], z = fa[y];
38         pushdown(y), pushdown(x);
39         int b = (lc[y] == x) ? rc[x] : lc[x];
40         //b是x的儿子,其方向要与x相反
41         fa[x] = z, fa[y] = x;
42         if (b) fa[b] = y;//对fa[]修改 
43         if (z) (y == lc[z] ? lc[z] : rc[z]) = x;
44         if (x == lc[y]) rc[x] = y, lc[y] = b;
45         else lc[x] = y, rc[y] = b;//对左右儿子修改 
46         pushup(y), pushup(x); 
47     }
48     void splay(int x, int tar) {
49         while (fa[x] != tar) {
50             if (fa[fa[x]] != tar)
51                 Wrt(x) == Wrt(fa[x]) ? rot(fa[x]) : rot(x);
52             rot(x);
53         }
54         if (!tar) rt = x;
55     }
56     int Find(int k) {//查找第k个数,返回其节点编号 
57         int x = rt, y = k;
58         while(x) {
59             pushdown(x);
60             if (y <= sze[lc[x]]) x = lc[x];
61             else {
62                 y -=sze[lc[x]] + 1;
63                 if (!y) return x;
64                 x = rc[x];
65             }
66         }
67     }
68 }
69 using namespace Splay;
70 void Print(int x) {
71     pushdown(x);
72     if (lc[x]) Print(lc[x]);
73     if (vi[x] != -inf && vi[x] != inf)
74         printf("%d ", vi[x]);
75     if (rc[x]) Print(rc[x]);
76 }
77 int main() {
78     n = read(), m = read();
79     a[1] = -inf, a[n + 2] = inf;
80     for (int i = 1; i <= n; i ++) a[i + 1] = i;
81     rt = build(0, 1, n + 2);
82     while (m --) {
83         int tx = Find(read());
84         int ty = Find(read() + 2);
85         splay(tx, 0); 
86         splay(ty, tx);
87         pos[lc[rc[rt]]] ^= 1;
88     }
89     Print(rt);
90     return 0;
91 }

 

posted @ 2022-04-04 14:34  YHXo  阅读(41)  评论(0编辑  收藏  举报