hdu3487 Play with Chain splay
来源:互联网 发布:云计算 开源框架 编辑:程序博客网 时间:2024/05/16 07:42
题意:
给你一个长度为n
的1~n
序列,要求实现以下两个操作: CUT i j c
:将FLIP i j
:将
思路:
用splay维护这段序列。
假设要对区间[l, r]
进行操作,则将l-1
旋转到根,r+1
旋转到根的右子树,则根的右子树的左子树就是区间[l, r]
。
很多操作都基于这个操作。
CUT:先将区间[l, r]
旋转到根的右子树的左子树,然后切下来。
要接上去,现将c旋转到根,再把根的右子树的最小值旋转到根的右子树,然后将切下来的区间接到根的右子树的左子树。
FLIP:找到区间[l, r]
,打上标记即可。
代码:
#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>#define MAXN 300005using namespace std;int n, q;int root, sz;int id[MAXN];int rev[MAXN];int siz[MAXN];int tr[MAXN][2];int fa[MAXN];void pushUp(int rt) { siz[rt] = siz[tr[rt][0]] + siz[tr[rt][1]] + 1;}void pushDown(int rt) { if (rev[rt]) { int l = tr[rt][0], r = tr[rt][1]; rev[rt] = 0; rev[l] ^= 1; rev[r] ^= 1; swap(tr[rt][0], tr[rt][1]); }}void rotate(int x, int &k) { int y = fa[x], z = fa[y]; int l, r; if (tr[y][0] == x) l = 0; else l = 1; r = l ^ 1; if (y == k) k = x; else { if (tr[z][0] == y) tr[z][0] = x; else tr[z][1] = x; } fa[x] = z; fa[y] = x; fa[tr[x][r]] = y; tr[y][l] = tr[x][r]; tr[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 (tr[y][0] == x ^ tr[z][0] == y) rotate(x, k); else rotate(y, k); } rotate(x, k); }}void build(int l, int r, int rt) { if (l > r) return; int now = id[l], last = id[rt]; if (l == r) { fa[now] = last; siz[now] = 1; if (l < rt) tr[last][0] = now; else tr[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 < rt) tr[last][0] = now; else tr[last][1] = now;}int find(int rt, int rank) { pushDown(rt); int l = tr[rt][0], r = tr[rt][1]; if (siz[l] + 1 == rank) return rt; if (siz[l] + 1 > rank) return find(l, rank); return find(r, rank - siz[l] - 1);}int find_min(int rt) { pushDown(rt); while (tr[rt][0]) { rt = tr[rt][0]; pushDown(rt); } return rt;}void rever(int l, int r) { int x = find(root, l); int y = find(root, r + 2); splay(x, root); splay(y, tr[root][1]); int z = tr[y][0]; rev[z] ^= 1;}void cut(int l, int r, int c) { int x = find(root, l); int y = find(root, r + 2); splay(x, root); splay(y, tr[root][1]); int temp = tr[y][0]; tr[y][0] = 0; pushUp(tr[root][1]); pushUp(root); int z = find(root, c + 1); splay(z, root); int m = find_min(tr[root][1]); splay(m, tr[root][1]); tr[tr[root][1]][0] = temp; fa[tr[tr[root][1]][0]] = tr[root][1]; pushUp(tr[root][1]); pushUp(root);}int main() { freopen("3487.in", "r", stdin); while (~scanf("%d %d", &n, &q)) { if (n == -1 && q == -1) break; sz = 0; for (int i = 1; i <= n + 2; i++) { id[i] = ++sz; rev[i] = fa[i] = siz[i] = tr[i][0] = tr[i][1] = 0; } build(1, n + 2, 0); root = n + 3 >> 1; char op[8]; int x, y, z; for (int i = 0; i < q; i++) { scanf("%s", op); if (op[0] == 'C') { cin >> x >> y >> z; cut(x, y, z); } else { cin >> x >> y; rever(x, y); } } for (int i = 2; i <= n + 1; i++) cout << find(root, i) - 1 << " \n"[i == n + 1]; } return 0;}
0 0
- 【hdu3487】【splay】Play with Chain
- hdu3487 Play with Chain(splay)
- HDU3487 Play with Chain (Splay)
- hdu3487 Play with Chain splay
- hdu3487 Play with Chain (Splay)
- Splay hdu3487 Play with Chain
- HDU3487 Play with Chain(Splay)
- hdu3487 Play with Chain(Splay)
- hdu3487 Play with Chain 伸展树splay
- hdu3487:Play with Chain (splay)
- hdu3487 Play with Chain
- #HDU3487#Play the Chain
- 【HDU3487】Play with Chain——伸展树
- HDU 3487 Play with Chain (Splay tree)
- hdu 3487 Play with Chain(splay)
- hdu 3487 Play with Chain(Splay)
- HDOJ 3487 Play with Chain【splay】
- HDU 3487 Play with Chain(Splay)
- 十一、内存管理中的循环引用
- 明正统年间
- 姐姐出嫁的那天,我是她唯一的亲人
- 查询网络端口被哪个进程/线程占用
- 基础练习 矩阵乘法
- hdu3487 Play with Chain splay
- HDU4553约会安排
- 【补遗】- OC学习小窍门及文件操作(归档)
- 第十八周项目4:点和距离
- 我和姐姐成了孤儿。
- Sicily 1307. TYLY Language
- POJ2115-C Looooops (错误分析)
- 兼容性问题测试和解决方案
- javaweb之filter