文艺平衡树 - 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; }
寻找真正的热爱