FHQtreap笔记
参考https://msd.misuland.com/pd/4425384081022256588
侵删。
变量
struct node {
int ls, //左儿子下标
rs, //右儿子下标
r, //随机权值
v, //权值
size; //树的大小
} tree[maxn];
int tot = 0;
新增节点
int New(int val) {
tree[++tot].v = val;
tree[tot].r = rand();
tree[tot].size=1;
return tot;
}
节点size更新
void upd(int x) {
tree[x].size = tree[tree[x].ls].size + tree[tree[x].rs].size + 1;
}
merge (合并)
//将以x,y为根的两棵树合并为一棵,并返回合并后的根节点编号。
//以x为根的树中所有任意的权值不大于以y为根的树中所有任意的权值。
//令r满足小根堆性质
int merge(int x, int y) {
if(!x || !y) return x | y;
if(tree[x].r < tree[y].r) {
tree[x].rs = merge(tree[x].rs, y); //把y插入到x右子树
upd(x);
return x;
}
else {
tree[y].ls = merge(x, tree[y].ls); //把x插入到y左子树
upd(y);
return y;
}
}
split (分离)
//将以p为根的树分裂为两棵树,根分别是x和y。
//其中x树中所有节点的权值小于等于val,y树中所有节点的权值大于val。
void split(int p, int val, int &x, int &y) {
if(!p) {
x = y = 0;
return;
}
if(tree[p].v <= val) {
x = p;
split(tree[p].rs, val, tree[p].rs, y); //右子树 小于val的节点留下来,大于val的传到y
}
else {
y = p;
split(tree[p].ls, val, x, tree[p].ls); //左子树 大于val的节点留下来,小于val的传到x
}
}
插入
分裂为小于等于val-1和大于等于val两棵子树x、y,然后New一个节点z值为val,依次合并x,y,z。
删除
两次split分裂成三棵子树分别是x,y,z,x<val,y=val,z>val。
如果只删除一个val,把y变为其两棵子树的合并,然后依次合并x,y,z。
如果全部删除,直接合并x,z。

浙公网安备 33010602011771号