平衡树——FHQ Treap

Posted Ariel_

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了平衡树——FHQ Treap相关的知识,希望对你有一定的参考价值。

前言

上文介绍了普通的平衡树,它简单(奇怪,鬼畜)的旋转操作确实死难写也难调(刚写挂一个),于是跑去学了一个不用旋转的平衡树,无旋 \\(Treap (FHQ~~Treap)\\)

只需要两个操作达到 \\(splay\\) 全部功能 ?? 太炫酷了

概况

\\(FHQ~~Treap\\) 和普通的 \\(Treap\\) 一样每个节点维护两个值,一个是权值,一个是随机值

但是它不再是用旋转来维护,而是通过 \\(split\\)\\(merge\\) 进行维护

操作

split(分树)

把一个 \\(Treap\\) 分成两个

两种:按权值分,按子树大小分

复杂度 \\(O(log n)\\)

按权值分

把权值小于 \\(k\\) 的节点都分到一棵树中,其余的点都分到另一棵树中

如果当前节点权值小于 \\(k\\) 那么它的左子树都会分到一棵树内,然后向右孩子查找

否则该节点的右节点都会分到另一个子树内,然后向右查找

    void split(int p, int k, int &x, int &y) {
        if (!p) x = y = 0;
        else {
            if (val[p] <= k) x = p, split(rs(p), k, rs(p), y);
            else y = p, split(ls(p), k, x, ls(p));
            update(p);
        }
    }

按子树大小分

把一棵树分成两棵树,其中一棵的大小为 \\(k\\)

\\(Treap\\)\\(Kth\\) 操作类似

如果当前点的左子树大小大于 \\(k\\) ,向左子树继续查找

否则的话该点的左子树一定在大小为 \\(k\\) 的树中,然后使右子树分出 \\(k - siz[p] - 1\\) 大小的子树

    int split(int p, int k, int &x, int &y) {
       if(!p) x = y = 0;
       else {
          if(k <= siz(ls(p)))
            y = p, split(ls(p), k, x, ls(p));
          else 
            x = p, split(rs(p), k - siz[ls(p)] - 1, rs(p), y);
          update(p);
       }
    }

merge(合并)

先咕着,明天写……

以上是关于平衡树——FHQ Treap的主要内容,如果未能解决你的问题,请参考以下文章

fhq-Treap 文艺平衡树代码记录

fhq treap

神仙数据结构——FHQ_Treap

fhq treap

fhq treap ------ luogu P3369 模板普通平衡树(Treap/SBT)

FHQ Treap小结(神级数据结构!)