伸展树模板
来源:互联网 发布:詹姆斯深蹲力量数据 编辑:程序博客网 时间:2024/06/05 02:32
给定一个数n,代表有一个数列1~n,有下面两种操作:
- CUT a b c 把区间[a,b]这一段元素切下来接到新序列第c个元素的后面
- FLIP a b 反转区间[a,b]
最后遍历整个序列
#define key_val son[son[root][1]][0]typedef long long ll;const int N = 300010, INF = 0x3f3f3f3f, MOD = 1000000;int son[N][2], fat[N], siz[N];int key[N], val[N], lazy[N];int root, tot, cnt;int arr[N];int n, m;void new_node(int val, int fa, int &x){ x = ++tot; fat[x] = fa, key[x] = val; siz[x] = 1, lazy[x] = 0; son[x][0] = son[x][1] = 0;}void push_up(int x){ siz[x] = siz[son[x][0]] + siz[son[x][1]] + 1;}void push_down(int x){ if(lazy[x]) { swap(son[x][0], son[x][1]); lazy[son[x][0]] ^= 1, lazy[son[x][1]] ^= 1; lazy[x] = 0; }}void Rotate(int x, int p){ int y = fat[x]; push_down(y); push_down(x); son[y][!p] = son[x][p], fat[son[x][p]] = y; if(fat[y]) son[fat[y]][son[fat[y]][1]==y] = x; fat[x] = fat[y]; son[x][p] = y, fat[y] = x; push_up(y);}void splay(int x, int goal){ push_down(x); while(fat[x] != goal) { int y = fat[x], z = fat[y]; //在这里下传翻转标记,在rotate里下传标记可能会使树形改变导致旋转出错 push_down(z); push_down(y); push_down(x); if(fat[y] == goal) Rotate(x, son[y][0] == x); else { int p = son[fat[y]][0] == y; if(son[y][p] == x) Rotate(x, !p), Rotate(x, p); else Rotate(y, p), Rotate(x, p); } } push_up(x); if(goal == 0) root = x;}int get_prec(int x){ push_down(x); x = son[x][0]; push_down(x); while(son[x][1]) x = son[x][1], push_down(x); return x;}int get_succ(int x){ push_down(x); x = son[x][1]; push_down(x); while(son[x][0]) x = son[x][0], push_down(x); return x;}int get_kth(int k){ int x = root; push_down(x); while(true) { if(k <= siz[son[x][0]]) x = son[x][0]; else if(k > siz[son[x][0]] + 1) k -= (siz[son[x][0]] + 1), x = son[x][1]; else break; push_down(x); } return x;}//int get_kth(int x, int k)//{// push_down(x);// if(k <= siz[son[x][0]]) return get_kth(son[x][0], k);// else if(k > siz[son[x][0]] + 1) return get_kth(son[x][1], k - siz[son[x][0]] - 1);// return x;//}void build(int l, int r, int fa, int &x){ if(l > r) return; int mid = (l + r) >> 1; new_node(mid, fa, x); build(l, mid-1, x, son[x][0]); build(mid+1, r, x, son[x][1]); push_up(x);}void cut(int a, int b, int c){ splay(get_kth(a), 0); splay(get_kth(b+2), root); int tmp = key_val; key_val = 0; push_up(son[root][1]), push_up(root); splay(get_kth(c+1), 0); splay(get_succ(root), root); key_val = tmp, fat[key_val] = son[root][1]; push_up(son[root][1]), push_up(root);}void rev(int a, int b){ splay(get_kth(a), 0); splay(get_kth(b+2), root); lazy[key_val] ^= 1;}void inorder(int x){ if(! x) return; push_down(x); inorder(son[x][0]); if(key[x] > 0) printf("%d%c", key[x], ++cnt == n ? '\n' : ' '); inorder(son[x][1]);}void init(){ root = tot = 0; son[0][0] = son[0][1] = siz[0] = fat[0] = 0; key[0] = val[0] = lazy[0] = 0; new_node(-INF, 0, root);//插入两个边界值,然后把序列插入两个边界值之间 new_node(-INF, root, son[root][1]); build(1, n, son[root][1], key_val); push_up(son[root][1]), push_up(root);}int main(){ char op[10]; int a, b, c; while(scanf("%d%d", &n, &m), n != -1 || m != -1) { init(); for(int i = 1; i <= m; i++) { scanf(" %s%d%d", op, &a, &b); if(op[0] == 'C') { scanf("%d", &c); cut(a, b, c); } else rev(a, b); } cnt = 0; inorder(root); } return 0;}
- 插入x数
- 删除x数(若有多个相同的数,因只删除一个)
- 查询x数的排名(若有多个相同的数,因输出最小的排名)
- 查询排名为x的数
- 求x的前驱(前驱定义为小于x,且最大的数)
- 求x的后继(后继定义为大于x,且最小的数)
const int N = 100000 + 10;int son[N][2], key[N], siz[N], fat[N], mul[N];int root, tot, prec, succ;void init(){ tot = root = 0;}void new_node(int val, int fa, int &x){ x = ++tot; fat[x] = fa, key[x] = val; siz[x] = mul[x] = 1; son[x][0] = son[x][1] = 0;}void push_up(int x){ siz[x] = siz[son[x][0]] + siz[son[x][1]] + mul[x];}void Rotate(int x, int p){ int y = fat[x]; son[y][!p] = son[x][p], fat[son[x][p]] = y; if(fat[y]) son[fat[y]][son[fat[y]][1]==y] = x; fat[x] = fat[y]; son[x][p] = y, fat[y] = x; push_up(y);}void splay(int x, int goal){ while(fat[x] != goal) { int y = fat[x]; if(fat[y] == goal) Rotate(x, son[y][0] == x); else { int p = son[fat[y]][0] == y; if(son[y][p] == x) Rotate(x, !p), Rotate(x, p); else Rotate(y, p), Rotate(x, p); } } push_up(x); if(goal == 0) root = x;}void Insert(int val){ int y = 0, x = root; while(x && key[x] != val) y = x, x = son[x][key[x]<val]; if(x) mul[x]++; else new_node(val, y, x); if(y) son[y][key[y]<val] = x; splay(x, 0);}int Find(int val){ int x = root; while(x && key[x] != val) x = son[x][key[x]<val]; return x;}int get_prec(int x){ x = son[x][0]; while(son[x][1]) x = son[x][1]; return x;}int get_succ(int x){//求x的后继 x = son[x][1]; while(son[x][0]) x = son[x][0]; return x;}void del(int val){ int x = Find(val); if(!x) return; splay(x, 0); if(mul[root] > 1) { siz[root]--, mul[root]--; return; } if(!son[root][0] || !son[root][1]) root = son[root][0] + son[root][1], fat[root] = 0; else { int t = get_succ(root); splay(t, root); son[son[root][1]][0] = son[root][0], root = son[root][1]; fat[son[root][0]] = root, fat[root] = 0; push_up(root); }}int get_kth(int k){ int x = root; while(true) { if(k > siz[son[x][0]] + mul[x]) k -= siz[son[x][0]] + mul[x], x = son[x][1]; else if(k <= siz[son[x][0]]) x = son[x][0]; else break; } return x;}//int get_kth(int x, int k)//{// if(k > siz[son[x][0]] + mul[x]) return get_kth(son[x][1], k - siz[son[x][0]] - mul[x]);// else if(k <= siz[son[x][0]]) return get_kth(son[x][0], k);// else return key[x];//}int get_rank(int val){//求排名很简洁 int x = Find(val); splay(x, 0); return siz[son[x][0]] + 1;}void get_prec(int x, int val){//查询前驱,val不一定存在与树中,如果存在于树中,那么旋转至根,就很容易求前驱了 if(x == 0) return; if(key[x] < val) { prec = key[x]; get_prec(son[x][1], val); } else get_prec(son[x][0], val);}void get_succ(int x, int val){//与求前驱同理 if(x == 0) return; if(key[x] > val) { succ = key[x]; get_succ(son[x][0], val); } else get_succ(son[x][1], val);}int main(){ int n, op, x; scanf("%d", &n); init(); while (n--) { scanf("%d%d", &op, &x); if (op == 1) Insert(x); else if (op == 2) del(x); else if (op == 3) printf("%d\n", get_rank(x)); else if (op == 4) printf("%d\n", key[get_kth(x)]); else if (op == 5) { get_prec(root, x); printf("%d\n", prec); } else { get_succ(root, x); printf("%d\n", succ); } } return 0;}
阅读全文
0 0
- Splay伸展树&模板
- 伸展树(splay)模板
- 伸展树模板
- 伸展树模板题
- 伸展树模板
- 伸展树模板
- Splay伸展树模板总结
- HDU 3487(伸展树模板)
- HDU4453(伸展树模板题)
- HNOI2002营业额统计 (伸展树---模板题)
- wikioi 1396 伸展树(两个模板)
- ACM常用模板——伸展树
- bzoj 1014伸展树 模板题
- 伸展树 模板(指针+数组)
- 伸展树模板小结(Splay Tree)
- 伸展树(SPLAY)个人总结+模板 [平衡树]【数据结构】【模板】
- 伸展树:双层伸展
- 【伸展树】[CQBZOJ2803]普通平衡树splay模板
- 【CodeForces429E】Points and Segments(欧拉回路)
- bitset+暴力——校门外的树
- 关于STS工具运行过程中使用Ctrl+right会自动退出的解决办法
- 从mysql 中批量导出数据
- 用ViewHolder优化显示性能
- 伸展树模板
- javaSE之对象相等问题
- 51nod 1122 机器人走方格 V4(矩阵快速幂)
- linux 下常用的解压命令
- Tyvj1075
- Java的历史
- CCF考试练习——201509-1
- poi报表导出excel
- 51nod 2026 Gcd and Lcm