模板_文艺平衡树(fhq-Treap)

$Problem’s\ Website$

文艺平衡树(洛谷)

文艺平衡树($\mathbb{LOJ}$)

$Problem’s\ Description$

  • 给定一个序列,每次操作使区间[$l - r$]翻转。

$Solution$

因为本人暂时不会$\mathfrak{Splay}$,所以这题我用$\mathfrak{fhq-Treap}$来写。

思路还是比较明确的,将要翻转的区间分裂出来,然后维护一个翻转标记(类似于线段树的$\mathrm{Lazy\ Tag}$)。

关于如何分裂,大家可以打一下草,我们先以$l - 1$将区间分成$r1,r2$两段,再在$r2$的区间中以序列长度($r-l+1$)分成$r2,r3$两段,那么$r2$就是目标区间。

$Code$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
//Coded by Dy.
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define gc getchar()
#define pc(x) putchar(x)
inline int sc() {
int xx = 0, ff = 1; char cch = gc;
while(!isdigit(cch)) {
if(cch == '-') ff = -1; cch = gc;
}
while(isdigit(cch)) {
xx = (xx << 1) + (xx << 3) + (cch ^ '0'); cch = gc;
}
return xx * ff;
}
inline void out(int x) {
if(x < 0)
pc('-'), x = -x;
if(x >= 10)
out(x / 10);
pc(x % 10 + '0');
}
#define re register
using std :: swap;
const int Maxn = 1e5 + 10;
int n, m;
int rt, r1, r2, r3, tot;
int ch[Maxn][2], val[Maxn], dat[Maxn], siz[Maxn];
bool tag[Maxn];
inline void pushup(int id) {
siz[id] = siz[ch[id][0]] + siz[ch[id][1]] + 1;
}
inline int cre(int k) {
siz[++tot] = 1, val[tot] = k, dat[tot] = rand();
return tot;
}
inline void pushdown(int id) {
if(!tag[id])
return;
swap(ch[id][0], ch[id][1]);
if(ch[id][0])
// pushdown(ch[id][0]);
tag[ch[id][0]] ^= 1;
if(ch[id][1])
// pushdown(ch[id][1]);
tag[ch[id][1]] ^= 1;
tag[id] = 0;
}
inline void split(int id, int k, int &x,int &y) {
if(!id)
x = y = 0;
else {
if(tag[id])
pushdown(id);
if(siz[ch[id][0]] + 1 <= k) {
x = id;
split(ch[id][1], k - siz[ch[id][0]] - 1, ch[id][1], y);
}
else {
y = id;
split(ch[id][0], k, x, ch[id][0]);
}
pushup(id);
}
}
inline int merge(int x, int y) {
if(!x || !y)
return x + y;
if(dat[x] < dat[y]) {
if(tag[x])
pushdown(x);
ch[x][1] = merge(ch[x][1], y);
pushup(x);
return x;
}
if(tag[y])
pushdown(y);
ch[y][0] = merge(x, ch[y][0]);
pushup(y);
return y;
}
inline void flist(int id) {
if(!id)
return;
if(tag[id])
pushdown(id);
flist(ch[id][0]);
out(val[id]), pc(' ');
flist(ch[id][1]);
}
int main() {
srand(20041029);
n = sc(), m = sc();
for(re int i = 1; i <= n; ++i)
rt = merge(rt, cre(i));
while(m--) {
int l = sc(), r = sc();
split(rt, l - 1, r1, r2);
split(r2, r - l + 1, r2, r3);
tag[r2] ^= 1;
rt = merge(r1, merge(r2, r3));
}
flist(rt);
return 0;
}

$\mathrm{rp++}$