[Bzoj3223][Tyvj1729] 文艺平衡树(splay/无旋Treap)

Posted sainsist

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Bzoj3223][Tyvj1729] 文艺平衡树(splay/无旋Treap)相关的知识,希望对你有一定的参考价值。

题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3223

平衡树处理区间问题的入门题目,普通平衡树那道题在维护平衡树上是以每个数的值作为维护的标准,而处理区间问题时,维护平衡树的应该是每个位置的下标,所以平衡树中序遍历时应该是当前区间的样子。例如:

1 2 3 4 5翻转区间1 3,则中序遍历应该输出3,2,1,4,5。

提供splay和无旋Treap的做法。

splay做法:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn = 1e5 + 10;
 5 int Siz[maxn], ls[maxn], rs[maxn], pos[maxn], lazy[maxn], root;
 6 int cnt;
 7 inline void up(int x) 
 8     Siz[x] = Siz[ls[x]] + Siz[rs[x]] + 1;
 9 
10 inline void down(int x) 
11     if (lazy[x]) 
12         swap(ls[x], rs[x]);
13         lazy[ls[x]] ^= 1;
14         lazy[rs[x]] ^= 1;
15         lazy[x] = 0;
16     
17 
18 void split_size(int x, int siz, int &A, int &B) 
19     if (x == 0)return (void)(A = B = 0);
20     down(x);
21     if (siz <= Siz[ls[x]])
22         B = x, split_size(ls[x], siz, A, ls[x]);
23     else
24         A = x, split_size(rs[x], siz - Siz[ls[x]] - 1, rs[x], B);
25     up(x);
26 
27 int Merge(int A, int B) 
28     if (A == 0 || B == 0)return A | B;
29     int ans;
30     down(A);
31     down(B);
32     if (pos[A] > pos[B])ans = A, rs[A] = Merge(rs[A], B);
33     else ans = B, ls[B] = Merge(A, ls[B]);
34     up(ans);
35     return ans;
36 
37 int build(int l, int r) 
38     if (l > r)return 0;
39     int mid = l + r >> 1;
40     ls[mid] = build(l, mid - 1);
41     rs[mid] = build(mid + 1, r);
42     pos[mid] = rand();
43     up(mid);
44     return mid;
45 
46 void dfs(int x) 
47     if (x) 
48         down(x);
49         dfs(ls[x]);
50         printf("%d ", x);
51         dfs(rs[x]);
52     
53 
54 int main() 
55     int n, m;
56     scanf("%d%d", &n, &m);
57     root = build(1, n);
58     while (m--) 
59         int l, r;
60         scanf("%d%d", &l, &r);
61         int A, B, C, D;
62         split_size(root, l - 1, A, B);
63         split_size(B, r - l + 1, C, D);
64         lazy[C] ^= 1;
65         root = Merge(A, Merge(C, D));
66     
67     dfs(root);
68     return 0;
69 

 

无旋Treap做法

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int inf = 2e9;
 5 const int maxn = 100010;
 6 int ch[maxn][2], siz[maxn], lazy[maxn], fa[maxn], val[maxn];
 7 int a[maxn];
 8 int root, cnt;
 9 void pushup(int x) 
10     siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + 1;
11 
12 void pushdown(int x) 
13     if (lazy[x]) 
14         if (ch[x][0])lazy[ch[x][0]] ^= 1;
15         if (ch[x][1])lazy[ch[x][1]] ^= 1;
16         swap(ch[x][0], ch[x][1]);
17         lazy[x] = 0;
18     
19 
20 void rotate(int x) //将x旋转到x的父亲的位置
21     int y = fa[x];
22     int z = fa[y];
23     pushdown(y); pushdown(x);
24     int k = (ch[y][1] == x);
25     ch[z][ch[z][1] == y] = x;
26     fa[x] = z;
27     ch[y][k] = ch[x][k ^ 1];
28     fa[ch[x][k ^ 1]] = y;
29     ch[x][k ^ 1] = y;
30     fa[y] = x;
31     pushup(y); pushup(x);
32 
33 void splay(int x, int goal) //将x旋转为goal的子节点
34     while (fa[x] != goal) 
35         int y = fa[x];
36         int z = fa[y];
37         if (z != goal)
38             (ch[y][1] == x) ^ (ch[z][1] == y) ? rotate(x) : rotate(y);
39         //如果x和y同为左儿子或者右儿子先旋转y
40         //如果x和y不同为左儿子或者右儿子先旋转x
41         rotate(x);
42     
43     if (goal == 0)
44         root = x;
45 
46 int build(int l, int r, int f) 
47     if (l > r)return 0;
48     int mid = l + r >> 1, now = ++cnt;
49     val[now] = a[mid], fa[now] = f, lazy[now] = 0;
50     ch[now][0] = build(l, mid - 1, now);
51     ch[now][1] = build(mid + 1, r, now);
52     pushup(now);
53     return now;
54 
55 int FindK(int root, int k) 
56     int now = root;
57     while (1) 
58         pushdown(now);
59         if (k <= siz[ch[now][0]])
60             now = ch[now][0];
61         else 
62             k -= siz[ch[now][0]] + 1;
63             if (k == 0)return now;
64             else now = ch[now][1];
65         
66     
67 
68 void rever(int l, int r) 
69     int ll = FindK(root, l);
70     int rr = FindK(root, r + 2);
71     splay(ll, 0);
72     splay(rr, ll);
73     pushdown(root);
74     lazy[ch[ch[root][1]][0]] ^= 1;
75 
76 void dfs(int x) 
77     pushdown(x);
78     if (ch[x][0])dfs(ch[x][0]);
79     if (val[x] != inf && val[x] != -inf)
80         printf("%d ", val[x]);
81     if (ch[x][1])dfs(ch[x][1]);
82 
83 int main() 
84     int n, m;
85     scanf("%d%d", &n, &m);
86     for (int i = 1; i <= n; i++)
87         a[i + 1] = i;
88     a[1] = -inf, a[n + 2] = inf;
89     root = build(1, n + 2, 0);
90     while (m--) 
91         int l, r;
92         scanf("%d%d", &l, &r);
93         rever(l, r);
94     
95     dfs(root);
96     //system("pause");
97 

 

以上是关于[Bzoj3223][Tyvj1729] 文艺平衡树(splay/无旋Treap)的主要内容,如果未能解决你的问题,请参考以下文章

bzoj3223 Tyvj 1729 文艺平衡树

[BZOJ3223]Tyvj 1729 文艺平衡树

bzoj3223: Tyvj 1729 文艺平衡树(splay翻转操作)

bzoj 3223: Tyvj 1729 文艺平衡树

[BZOJ3223] [Tyvj1729] 文艺平衡树 (splay)

BZOJ3223: Tyvj 1729 文艺平衡树