不同于普通 Treap,FHQ-Treap 不需要左旋和右旋操作来处理数据。因此 FHQ-Treap 也称作无旋 Treap。
FHQ-Treap 是基于 Split(分裂)和 Merge(合并)两种操作的平衡树。其与普通 Treap 的原理完全不同。
一些基础的操作:例如 Insert(插入元素)和 Delete(删除元素)。
对于 Insert(插入元素),新建一棵只有一个元素的 FHQ-Treap,再将这棵 Treap 与之前的 Treap 合并即可。
对于 Delete(删除元素),将这棵 Treap 中的某个元素从其中分裂出去,即可视作已经删除。
而其他一些普通 Treap 能够做到的操作它也能做到。一切都是因为最关键的 Split(分裂)和 Merge(合并)。
Split —— 分裂
Split(int p,int val,int &l,int &r)
一般每次 Split 操作会将当前的 Treap 分裂成一棵 \(\le\) 分裂标准的 Treap 和一棵 \(>\) 分裂标准的 Treap。
其包含四个参数,\(p\) 和 \(val\) 以及 \(l\) 和 \(r\)。
其中 \(p\) 表示当前枚举到的 Treap 的根,\(val\) 表示此次分裂操作的分裂标准。
其中带&
的 \(l\) 和 \(r\) 则记录分裂后两颗 Treap 的根。
我们现在枚举到了一颗 Treap,于是有:
-
若当前枚举到的 Treap 的根的权值 \(\le\) 分裂标准,因为左子树内的所有权值必定都 \(\le\) 分裂标准,则不需要继续考虑左子树,直接进入右子树。
-
若当前枚举到的 Treap 的根的权值 \(>\) 分裂标准,因为右子树内的所有权值必定都 \(>\) 分裂标准,则不需要继续考虑右子树,直接进入左子树。
递归 Split 即可。
Code:
void Split(int p,int val,int &l,int &r){
if(!p){
l=r=0;
return ;
}
if(Treap[p].val<=val) l=p,Split(Treap[p].r,val,Treap[p].r,r);
else r=p,Split(Treap[p].l,val,l,Treap[p].l);
pushup(p);
return ;
}
标签:val,int,码量,Treap,分裂,Split,FHQ
From: https://www.cnblogs.com/HAM-qwq/p/18329888