文艺平衡树 - FHQ treap
https://www.luogu.com.cn/problem/P3391
这平衡树太厉害了。
思想就是分裂成1--x-1 x---y y---n三段,然后给x----y这段树打上lazy标记,
在合并和分裂时候都要先下传标记才行
具体看代码就好,留个模板记录一下
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int maxn = 1e6 + 111;
struct Node {
int val, key;
int l, r, siz;
}tree[maxn];
int cnt = 0;
int lazy[maxn];
void add(int x) {
++cnt;
tree[cnt].val = x;
tree[cnt].l = tree[cnt].r = 0;
tree[cnt].siz = 1;
tree[cnt].key = rand();
}
void push(int node) {
swap(tree[node].l, tree[node].r);
lazy[tree[node].l] ^= 1;
lazy[tree[node].r] ^= 1;
lazy[node] = 0;
}
void update(int node) {
tree[node].siz = tree[tree[node].l].siz + tree[tree[node].r].siz + 1;
}
void split(int node, int x, int& l, int& r) {
if (node == 0) {
l = r = 0;
return ;
}
if (lazy[node]) push(node);//标记下传
if (tree[tree[node].l].siz + 1 <= x) {
l = node;
split(tree[node].r, x - tree[tree[node].l].siz - 1, tree[node].r, r);
//当前树的右子树也有部分要切成l集合
}
else {
r = node;
split(tree[node].l, x, l, tree[node].l);
}
update(node);
}
int merge(int l, int r) {
if (!l || !r) return l + r;
if (tree[l].key < tree[r].key) {
if (lazy[l]) push(l);
tree[l].r = merge(tree[l].r, r);
update(l);
return l;
}
else {
if (lazy[r]) push(r);
tree[r].l = merge(l, tree[r].l);
update(r);
return r;
}
}
int root, l, r, p;
int dfs(int x) {
if (x == 0) return 0;
if (lazy[x]) push(x);
dfs(tree[x].l);
printf("%d ", tree[x].val);
dfs(tree[x].r);
return 0;
}
int main() {
int n, m;
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++) {
add(i);
root = merge(root, cnt);
}
for (int i = 0; i < m; i++) {
int x, y;
scanf("%d %d", &x, &y);
split(root, y, l, r);
split(l, x - 1, l, p);
//p树部分
lazy[p] ^= 1;
root = merge(merge(l, p), r);
}
dfs(root);
return 0;
}
寻找真正的热爱

浙公网安备 33010602011771号