[bzoj3223]文艺平衡树——splay
2017-02-27 10:09
260 查看
题意
你应当编写一个数据结构,支持以下操作:
- 反转一个区间
题解
我们把在数组中的位置当作权值,这样原序列就在这种权值意义下有序,我们考虑使用splay维护。
对于操作rev[l,r],我们首先把l-1 splay 到根,再把r+1 splay 到根的右子树的根,那么根的右子树的左子树就是区间[l,r]。
显然,这样会用到l-1和r+1。我们考虑添加两个哨兵节点,分别是1和n+2,[1,n]的值再分别加一就好了。
另外,为了防止过多的swap,我们延续线段树中的做法, 打一个lazy标记。与线段树不同的是,由于splay的拓扑结构经常会变化,所以每访问到一个节点,都要下传lazy标记。
注意build的写法。
代码
#include <bits/stdc++.h> using namespace std; int n, m, sz, rt; #ifdef DEBUG const int maxn = 100; #else const int maxn = 100005; #endif int fa[maxn], c[maxn][2], id[maxn]; int size[maxn]; bool rev[maxn]; void pushup(int k) { int l = c[k][0], r = c[k][1]; size[k] = size[l] + size[r] + 1; } void pushdown(int k) { int &l = c[k][0], &r = c[k][1]; if (rev[k]) { swap(l, r); rev[l] ^= 1; rev[r] ^= 1; rev[k] = 0; } } void zig(int x, int &k) { // do one zig int y = fa[x], z = fa[y], l, r; // y:father z:grandfather if (c[y][0] == x) { // zig l = 0; } else l = 1; // zag r = l ^ 1; if (y == k) k = x; // single zig else { // update grandfather if (c[z][0] == y) c[z][0] = x; // zig-zig else c[z][1] = x; } fa[x] = z; fa[y] = x; fa[c[x][r]] = y; c[y][l] = c[x][r]; c[x][r] = y; pushup(y); pushup(x); } void splay(int x, int &k) { while (x != k) { int y = fa[x], z = fa[y]; if (y != k) { if (c[y][0] == x ^ c[z][0] == y) // diff:zig-zag or zag-zig zig(x, k); else // same:zig-zig or zag-zag zig(y, k); } zig(x, k); } } int find(int k, int rank) { pushdown(k); int l = c[k][0], r = c[k][1]; if (size[l] + 1 == rank) return k; else if (size[l] >= rank) return find(l, rank); else return find(r, rank - size[l] - 1); } void rever(int l, int r) { int x = find(rt, l), y = find(rt, r + 2); splay(x, rt); splay(y, c[x][1]); int z = c[y][0]; rev[z] ^= 1; } void build(int l, int r, int f) { // f:last node if (l > r) return; int now = id[l], last = id[f]; if (l == r) { fa[now] = last; size[now] = 1; if (l < f) c[last][0] = now; else c[last][1] = now; return; } int mid = (l + r) >> 1; now = id[mid]; build(l, mid - 1, mid); build(mid + 1, r, mid); fa[now] = last; pushup(mid); if (mid < f) { c[last][0] = now; } else c[last][1] = now; return; } int main() { #ifdef DEBUG freopen("input", "r", stdin); #endif scanf("%d %d", &n, &m); for (int i = 1; i <= n + 2; i++) id[i] = ++sz; build(1, n + 2, 0); rt = (n + 3) >> 1; for (int i = 1; i <= m; i++) { int l, r; scanf("%d %d", &l, &r); rever(l, r); } for (int i = 2; i <= n + 1; i++) { printf("%d ", find(rt, i) - 1); } return 0; }
相关文章推荐
- [BZOJ3223] 文艺平衡树 - splay
- 【BZOJ3223】Tyvj 1729 文艺平衡树【Splay】
- 【Splay】【块状链表】bzoj3223 Tyvj 1729 文艺平衡树
- BZOJ 3223 文艺平衡树 【Splay】
- _bzoj3223 Tyvj 1729 文艺平衡树【Splay】
- BZOJ_3223: Tyvj 1729 文艺平衡树 _splay
- bzoj 3223 Tyvj 1729 文艺平衡树 Splay
- bzoj 3223 文艺平衡树 - Splay
- 【bzoj3223】文艺平衡树 Splay & Treap
- splay区间翻转bzoj 3223(tyvj 1729)文艺平衡树题解
- bzoj 3223 文艺平衡树 Splay 打标志
- bzoj 3223 文艺平衡树 Splay详细解析
- 【bzoj3223】文艺平衡树【Splay】【呵呵】
- 【bzoj3223】Tyvj 1729 文艺平衡树 Splay
- 【BZOJ3223】文艺平衡树,Splay反转区间
- BZOJ 3223 文艺平衡树 splay
- bzoj3223 Tyvj1729 文艺平衡树 splay
- bzoj 3223 文艺平衡树 Splay
- BZOJ 3223: Tyvj 1729 文艺平衡树 splay
- bzoj 3223/tyvj 1729 文艺平衡树 splay tree