【BZOJ 3223】 文艺平衡树
【题目链接】
【算法】
本题是splay区间操作的模板题
我们每个点的权值设为”当前在序列中的排名“,根据二叉排序树的性质,这棵树的中序遍历就是当前序列
如果我们要获得一段区间[l,r],那么我们将l-1splay到根节点,将r+1splay到根节点的右子树的根,我们发现,根节点
的右节点的左子树就是区间[l,r]
对于翻转操作,我们其实只需将“根节点的右节点的左子树”这棵树不断地进行左右子树交换就可以了,但是,为了避免
交换次数太多,我们可以像线段树那样,每个点都存一个懒惰标记
【代码】
#include<bits/stdc++.h> using namespace std; #define MAXN 100000 int i,N,M,l,r; template <typename T> inline void read(T &x) { int f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) { if (c == '-') f = -f; } for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } template <typename T> inline void write(T x) { if (x < 0) { putchar('-'); x = -x; } if (x > 9) write(x/10); putchar(x%10+'0'); } template <typename T> inline void writeln(T x) { write(x); puts(""); } struct Splay { int root,total; struct Node { int size,val,son[2],fa; bool rev; } Tree[MAXN+10]; inline bool get(int x) { return Tree[Tree[x].fa].son[1] == x; } inline void update(int index) { Tree[index].size = Tree[Tree[index].son[0]].size + Tree[Tree[index].son[1]].size + 1; } inline void build(int index,int l,int r) { int mid = (l + r) >> 1; Tree[index].rev = false; Tree[index].val = mid; Tree[index].size = 1; if (l == r) return; if (l <= mid - 1) { ++total; Tree[index].son[0] = total; Tree[total].fa = index; build(total,l,mid-1); Tree[index].size += Tree[Tree[index].son[0]].size; } if (mid + 1 <= r) { ++total; Tree[index].son[1] = total; Tree[total].fa = index; build(total,mid+1,r); Tree[index].size += Tree[Tree[index].son[1]].size; } } inline void rotate(int x) { int f = Tree[x].fa,g = Tree[f].fa, tmpx = get(x),tmpf = get(f); if (Tree[f].rev) pushdown(f); if (Tree[x].rev) pushdown(x); if (!f) return; Tree[f].son[tmpx] = Tree[x].son[tmpx^1]; if (Tree[x].son[tmpx^1]) Tree[Tree[x].son[tmpx^1]].fa = f; Tree[x].son[tmpx^1] = f; Tree[f].fa = x; Tree[x].fa = g; if (g) Tree[g].son[tmpf] = x; update(f); update(x); } inline void splay(int x) { int f; for (f = Tree[x].fa; (f = Tree[x].fa); rotate(x)) if (Tree[f].fa) rotate(get(x) == get(f) ? f : x); root = x; } inline void splayII(int x) { int f; for (f = Tree[x].fa; (f = Tree[x].fa) != root; rotate(x)) { if (Tree[f].fa != root) rotate(get(x) == get(f) ? f : x); } } inline void pushdown(int index) { swap(Tree[index].son[0],Tree[index].son[1]); Tree[Tree[index].son[0]].rev ^= 1; Tree[Tree[index].son[1]].rev ^= 1; Tree[index].rev = 0; } inline int query_pos(int x) { int index = root; while (true) { if (Tree[index].rev) pushdown(index); if (x <= Tree[Tree[index].son[0]].size) index = Tree[index].son[0]; else { x -= Tree[Tree[index].son[0]].size; if (x == 1) return index; --x; index = Tree[index].son[1]; } } } inline int query_val(int x) { int pos = query_pos(x); return Tree[pos].val; } inline void reverse(int l,int r) { int x = query_pos(l-1), y = query_pos(r+1); splay(x); splayII(y); Tree[Tree[Tree[root].son[1]].son[0]].rev ^= 1; } } T; int main() { read(N); read(M); T.total = 1; T.root = 1; T.build(1,1,N+2); while (M--) { read(l); read(r); T.reverse(l+1,r+1); } for (i = 2; i <= N + 1; i++) { if (i == 2) write(T.query_val(i)-1); else { putchar(' '); write(T.query_val(i)-1); } } putchar(' '); puts(""); return 0; }