3223 Tyvj 1729 文藝平衡樹——splay區間翻轉
阿新 • • 發佈:2019-01-22
剛開始學spaly,所以一上來不會打標記,後來想了想splay的區間操作和線段樹其實基本一樣。
lazy標記的下推注意一下, update時如果直接進行splay操作的話會因lazy標記沒有下推而出錯,正確做法是在splay操作前先進行一個區間第k大查詢操作(因為區間反轉破壞了二叉搜尋樹的性質,所以我們只能進行區間第k大的查詢來輔助下推)
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn = 1e5 + 10; int n, m; struct Splay { int sz, root, fa[maxn], ch[maxn][2], key[maxn], size[maxn], lazy[maxn]; void newnode(int x, int f, int v) { fa[x] = f, key[x] = v; size[x] = 1; } void pushup(int x) { if (!x) return; size[x] = size[ch[x][0]] + size[ch[x][1]] + 1; } void pushdown(int x) { if (!x || !lazy[x]) return; lazy[ch[x][0]] ^= 1; lazy[ch[x][1]] ^= 1; swap(ch[ch[x][0]][0], ch[ch[x][0]][1]); swap(ch[ch[x][1]][0], ch[ch[x][1]][1]); lazy[x] = 0; } int build(int l, int r, int f) { if (l > r) return 0; int mid = (l + r) >> 1; int x = ++sz; newnode(x, f, mid); ch[x][0] = build(l, mid-1, x); ch[x][1] = build(mid+1, r, x); pushup(x); return x; } int pos(int x) { return ch[fa[x]][1] == x; } void rotate(int x) { int y = fa[x], z = fa[y], posx = pos(x), posy = pos(y); ch[y][posx] = ch[x][posx^1]; fa[ch[y][posx]] = y; ch[x][posx^1] = y; fa[y] = x; fa[x] = z; if (z) ch[z][posy] = x; pushup(y); pushup(x); } void splay(int x, int y) { for (int f; (f=fa[x]) != y; rotate(x)) { if (fa[f] != y) rotate(pos(x) == pos(f)?f:x); } if (y == 0) root = x; } int kth(int x, int k) { pushdown(x); if (size[ch[x][0]]+1 == k) return x; if (size[ch[x][0]]+1 > k) return kth(ch[x][0], k); else return kth(ch[x][1], k-size[ch[x][0]]-1); } void update(int l, int r) { int x = kth(root, l), y = kth(root, r); splay(x, 0); splay(y, x); int z = ch[y][0]; swap(ch[z][0], ch[z][1]); lazy[z] ^= 1; } void query(int x) { if (!x) return; pushdown(x); query(ch[x][0]); if (1 <= key[x]-1 && key[x]-1 <= n) printf("%d ", key[x]-1); query(ch[x][1]); } }ac; int main() { int l, r; scanf("%d%d", &n, &m); ac.root = ac.build(1, n+2, 0); while (m--) { scanf("%d%d", &l, &r); l++, r++; ac.update(l-1, r+1); } ac.query(ac.root); printf("\n"); return 0; }