非旋转 Treap 学习笔记(二)
2017-11-21 09:35
295 查看
非旋转 Treap 学习笔记(一) 没有涉及一些区间的操作只是最基本的 Treap 操作,这篇才是非旋 Treap 真正优秀的地方。
要注意涉及区间操作时插入就是按照位置插入的,而不是按照权值的排名插入了。
Luogu P3391 【模板】文艺平衡树(Splay)
插入的时候分离前
比如 1 2 3 4 5,在第 3 个位置插入一个 8,变成 1 2 8 3 4 5
把前面 1 2 分裂出来,后面 3 4 5 分裂出来
将
在 pushDown 时翻转,就是将标记的节点 v 的左右子树交换,并不断将标记下传。
每次在 split 和 merge 的时候记得 pushDown。
最后 dfs 中序遍历一次求出最终翻转后的数列。
要注意涉及区间操作时插入就是按照位置插入的,而不是按照权值的排名插入了。
Luogu P3391 【模板】文艺平衡树(Splay)
插入的时候分离前
pos - 1个。
比如 1 2 3 4 5,在第 3 个位置插入一个 8,变成 1 2 8 3 4 5
把前面 1 2 分裂出来,后面 3 4 5 分裂出来
将
1 ~ n分为
1 ~ (l - 1), l ~ r, (r + 1) ~ n找到要翻转的区间
l ~ r并标记。
在 pushDown 时翻转,就是将标记的节点 v 的左右子树交换,并不断将标记下传。
每次在 split 和 merge 的时候记得 pushDown。
最后 dfs 中序遍历一次求出最终翻转后的数列。
#include <bits/stdc++.h> using namespace std; const int N = 1e5 + 5; struct Treap { struct Node { Node *lc, *rc; int x, size, key; bool rev; Node(int x) : lc(NULL), rc(NULL), x(x), size(1), key(rand() * rand() * rand()), rev(false) {} inline void reverse() { rev ^= 1; } inline void pushDown() { if (rev) { swap(lc, rc); if (lc) lc->reverse(); if (rc) rc->reverse(); rev = false; } } inline void maintain() { size = (lc ? lc->size : 0) + (rc ? rc->size : 0) + 1; } inline int lSize() { return lc ? lc->size : 0; } } *root; /*int lowerCount(int x) { Node *v = root; int res = 0; while (v) { v->pushDown(); if (x <= v->x) v = v->lc; else res += v->lSize() + 1, v = v->rc; } return res; } int upperCount(int x) { Node *v = root; int res = 0; while (v) { v->pushDown(); if (x < v->x) v = v->lc; else res += v->lSize() + 1, v = v->rc; } return res; }*/ inline void split(Node *v, int k, Node *&l, Node *&r) { if(!v) { l = r = NULL; return ; } v->pushDown(); int s = v->lSize(); if(k <= s) { split(v->lc, k, l, r); v->lc = r; r = v; } else { split(v->rc, k - s - 1, l, r); v->rc = l; l = v; } v->maintain(); } Node *merge(Node *a, Node *b) { if (!a && !b) return NULL; if (!a) { b->maintain(); return b; } // if (!b) { a->maintain(): return a; } a->pushDown(); b->pushDown(); if (a->key > b->key) { a->rc = merge(a->rc, b); a->maintain(); return a; } else { b->lc = merge(a, b->lc); b->maintain(); return b; } } inline void insert(int pos, int x) { Node *pred, *tmp; split(root, pos - 1, pred, tmp); Node *v = new Node(x); root = merge(pred, merge(v, tmp)); } bool reverse(int l, int r) { Node *pred, *tmp; split(root, l - 1, pred, tmp); Node *target, *succ; split(tmp, r - l + 1, target, succ); target->reverse(); root = merge(pred, merge(target, succ)); } void dfs(Node *v, int *&p) { if (!v) return ; v->pushDown(); dfs(v->lc, p); *p ++ = v->x; dfs(v->rc, p); } void fetch(int a[]) { // p 是引用,会在整个递归过程中改变 int *p = &a[1]; dfs(root, p); } } treap; int main() { int n, m; scanf("%d%d", &n, &m); for (int i = 1; i <= n; i ++) treap.insert(i, i); for (int i = 1; i <= m; i ++) { int l, r; scanf("%d%d", &l, &r); treap.reverse(l, r); } static int a ; treap.fetch(a); // 中序遍历一遍 for (int i = 1; i <= n; i ++) printf("%d%c", a[i], " \n"[i ==n]); return 0; }
相关文章推荐
- 非旋转 Treap 学习笔记(一)
- (转)cocos2d-x学习笔记(五)仿真树叶飘落效果的实现(精灵旋转、翻转、钟摆运动等综合运用)
- [中级数据结构学习笔记]一、Treap
- Three.js 学习笔记(1)--坐标体系和旋转
- opencv3学习笔记(二)图像的截图,旋转与大小的变化
- 红黑树 学习笔记2 - 旋转
- webgl学习笔记三-平移旋转缩放
- transform-origin学习笔记之旋转与基点的关系
- 无旋Treap学习笔记+例题
- Directx11学习笔记【十二】 画一个旋转的彩色立方体
- Android ExifInterface 学习笔记,图片旋转的操作。
- WPF学习笔记---图片旋转(1)
- Android 学习笔记之Bitmap位图的旋转
- Treap 学习笔记
- Flash/Flex学习笔记(42):坐标旋转
- 3D数学--学习笔记(三):3D中绕任意轴的旋转
- Android ExifInterface 学习笔记,图片旋转的操作。
- Windows 8 Directx 开发学习笔记(十)纹理贴图实现旋转的木箱
- 平衡树:treap学习笔记(1)
- Unity学习笔记——旋转与角度