浅谈 FHQ Treap

浅谈 FHQ Treap

简单介绍

FHQ Treap,以下简写为 f h q fhq fhq,是一种treap(树堆)的变体,功能比treap强大。
f h q fhq fhq 不需要通过一般平衡树的左右旋转来保持平衡,而是通过分裂 s p l i t split split和合并 m e r g e merge merge 来实现操作。

优点是比较好理解、代码短、上手快、可持久化

主要是不用像 s p l a y splay splay 一样旋来旋去。

Treap比较好玩的一点是,它整体是拥有二叉搜索树的性质,但是它的每一个节点都会有一个附加权值,它的附加权值是符合堆的性质。

这样我们可以明显看出,这棵树的形态(平衡与否)是由这个附加权值决定的。

那我们该如何取这个权值呢?随机!!

是的,我们每次都随机一个权值作为它的附加权值,那么它就大概是平衡的。

只需要两个基础操作,就可以达到splay的所有功能

前置操作

结构

对于每个树上节点开一个结构体,维护左儿子、右儿子、两个权值、还有子树中的节点个数。

然后给定一个树上的权值 v v v​ ,新建节点,还有更新子树大小 u p d a t e update update

struct fhq {
   
    int l , r , v , t , sz;
} tr[N];
void update (int x) {
    tr[x].sz = 1 + tr[tr[x].l].sz + tr[tr[x].r].sz; }
int new_pos (int v) {
   
    tr[++pos].sz = 1;
    tr[pos].v = v;
    tr[pos].t = rnd ();
    return pos;
}

r n d ( ) rnd() rnd() 是随机数生成函数,需要搞一个预处理

std::mt19937 rnd(233);

分裂 split

这个的主要思想就是把一个 t r e a p treap treap 按照一个权值 v v v 分成两个。

把所有小于等于 v v v 的分到一棵树中,把所有大于 v v v 的分到另一棵树中,如下图。

3142227-20240519195920075-1936927548.png (1360×382) (cnblogs.com)

可以对照代码感性理解一下

void split (int now , int k , int &x , int &y) {
   
    if (now == 0) x = y = 0;
    else {
   
        if (tr[now].v <= k) 
            x = now , split (tr[now].r , k , tr[now].r , y);
        else 
            y = now , split (tr[now].l , k , x , tr[now].l);
        update (no
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值