无旋Treap学习
核心操作
-
split:
void split(int rt, int & a, int & b, int sz) //按size分 { if (rt == 0) { a = b = 0; return; } flip(rt); if (tree[tree[rt].lc].sz <= sz-1) { a = rt; split(tree[rt].rc, tree[a].rc, b, sz-tree[tree[rt].lc].sz-1); } else { b = rt; split(tree[rt].lc, a, tree[b].lc, sz); } update(rt); } void split(int rt, int & a, int & b, int val) //按权值分 { if (rt == 0) { a = b = 0; return; } if (tree[rt].val <= val) { a = rt; split(tree[rt].rc, tree[a].rc, b, val); } else { b = rt; split(tree[rt].lc, a, tree[b].lc, val); } update(rt); }
-
merge:
void merge(int & rt, int a, int b) { // 前提:a的权值全部 < b的权值 if (a == 0 || b == 0) { rt = a + b; return; } flip(a); flip(b); if (tree[a].rnk < tree[b].rnk) { rt = a; merge(tree[rt].rc, tree[a].rc, b); } else { rt = b; merge(tree[rt].lc, a, tree[b].lc); } update(rt); }
完整代码
也是模板题普通平衡树AC代码。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 7;
const int INF = 1e9;
struct node
{
int val, rnk, lc, rc, sz;
}tree[maxn];
int tot, seed = 233, root = 0;
inline int rrand()
{
return seed = int(seed * 482711ll % 2147483647);
}
inline void update(int rt)
{
tree[rt].sz = tree[tree[rt].lc].sz + tree[tree[rt].rc].sz + 1;
}
int add_node(int val)
{
tree[++tot].sz = 1;
tree[tot].val = val;
tree[tot].lc = tree[tot].rc = 0;
tree[tot].rnk = rrand();
return tot;
}
void split(int rt, int & a, int & b, int val)
{
if (rt == 0) {
a = b = 0;
return;
}
if (tree[rt].val <= val)
{
a = rt;
split(tree[rt].rc, tree[a].rc, b, val);
}
else
{
b = rt;
split(tree[rt].lc, a, tree[b].lc, val);
}
update(rt);
}
void merge(int & rt, int a, int b)
{
// 前提:a的权值全部 < b的权值
if (a == 0 || b == 0) {
rt = a + b;
return;
}
if (tree[a].rnk < tree[b].rnk) {
rt = a;
merge(tree[rt].rc, tree[a].rc, b);
}
else
{
rt = b;
merge(tree[rt].lc, a, tree[b].lc);
}
update(rt);
}
void insert(int & rt, int val)
{
// 插入一个值为val的节点
int x = 0, y = 0, nnode = add_node(val);
split(rt, x, y, val);
merge(x, x, nnode);
merge(rt, x, y);
}
void delete_node(int & rt, int val)
{
// 删除值为val的节点
int x = 0, y = 0, z = 0;
split(rt, x, y, val);
split(x, x, z, val - 1);
merge(z, tree[z].lc, tree[z].rc);
merge(x, x, z);
merge(rt, x, y);
}
int get_kth(int rt, int k) {
// 找第k大的数值
while (tree[tree[rt].lc].sz + 1 != k) {
if (tree[tree[rt].lc].sz >= k)
rt = tree[rt].lc;
else {
k -= tree[tree[rt].lc].sz + 1;
rt = tree[rt].rc;
}
}
return tree[rt].val;
}
int get_rank(int & rt, int val) {
// 查找值对应第几大
int x = 0, y = 0;
split(rt, x, y, val - 1);
int tmp = tree[x].sz + 1;
merge(rt, x, y);
return tmp;
}
int get_pre(int & rt, int val)
{
// 找值为val的前驱节点数值
int x = 0, y = 0;
split(rt, x, y, val - 1);
int tmp = get_kth(x, tree[x].sz);
merge(rt, x, y);
return tmp;
}
int get_suf(int & rt, int val)
{
// 找值为val的后继节点数值
int x = 0, y = 0;
split(rt, x, y ,val);
int tmp = get_kth(y, 1);
merge(rt, x, y);
return tmp;
}
int n;
int main() {
scanf("%d", &n);
int op, val;
/*add_node(INF);
tot = 1;
tree[1].sz = 0;
root = 1;
*/
for (int i = 1; i <= n; ++i) {
scanf("%d %d", &op, &val);
if (op == 1) {
insert(root, val);
} else if (op == 2) {
delete_node(root, val);
} else if (op == 3) {
printf("%d\n", get_rank(root, val));
} else if (op == 4) {
printf("%d\n", get_kth(root, val));
} else if (op == 5) {
printf("%d\n", get_pre(root, val));
} else {
printf("%d\n", get_suf(root, val));
}
}
return 0;
}
题目记录(持续更新)
-
要实现翻转操作,本题需要按size分,分出1l-1,lr,r+1~n三段,给第二段打上标记。同时在分裂,合并以及最后求解的操作时都要下放标记。
#include <bits/stdc++.h> using namespace std; const int maxn = 1e6 + 7; const int INF = 1e9; struct node { int val, rnk, lc, rc, sz; }tree[maxn]; int tot, seed = 233, root = 0; inline int rrand() { return seed = int(seed * 482711ll % 2147483647); } int fl[maxn]; inline void update(int rt) { tree[rt].sz = tree[tree[rt].lc].sz + tree[tree[rt].rc].sz + 1; } int add_node(int val) { tree[++tot].sz = 1; tree[tot].val = val; tree[tot].lc = tree[tot].rc = 0; tree[tot].rnk = rrand(); return tot; } void flip(int rt) { if(fl[rt]) { swap(tree[rt].lc,tree[rt].rc); if(tree[rt].lc) fl[tree[rt].lc]^=1; if(tree[rt].rc) fl[tree[rt].rc]^=1; fl[rt]=0; } } void split(int rt, int & a, int & b, int sz) { if (rt == 0) { a = b = 0; return; } flip(rt); if (tree[tree[rt].lc].sz <= sz-1) { a = rt; split(tree[rt].rc, tree[a].rc, b, sz-tree[tree[rt].lc].sz-1); } else { b = rt; split(tree[rt].lc, a, tree[b].lc, sz); } update(rt); } void merge(int & rt, int a, int b) { // 前提:a的权值全部 < b的权值 if (a == 0 || b == 0) { rt = a + b; return; } flip(a); flip(b); if (tree[a].rnk < tree[b].rnk) { rt = a; merge(tree[rt].rc, tree[a].rc, b); } else { rt = b; merge(tree[rt].lc, a, tree[b].lc); } update(rt); } void insert(int & rt, int val) { // 插入一个值为val的节点 int x = 0, y = 0, nnode = add_node(val); split(rt, x, y, val); merge(x, x, nnode); merge(rt, x, y); } vector<int> ans; void dfs(int rt) { flip(rt); if(tree[rt].lc) dfs(tree[rt].lc); ans.push_back(tree[rt].val); if(tree[rt].rc) dfs(tree[rt].rc); } int n,m; int main() { scanf("%d%d", &n,&m); for(int i=1;i<=n;i++) { insert(root,i); } int l,r; for(int i=1;i<=m;i++) { scanf("%d%d",&l,&r); int a=0,b=0,c=0; split(root,a,b,l-1); split(b,b,c,r-l+1); flip(b); fl[b]=1; merge(a,a,b); merge(root,a,c); } dfs(root); for(int i=0;i<ans.size();i++) { printf("%d%c",ans[i],i==ans.size()-1?'\n':' '); } return 0; }