平衡树(无旋treap)学习笔记

这里主要是讲无旋Treap,比较好维护,能实现大量功能,并且可持久化。

缺点在于常数大,码量大,并且时间复杂度期望为 \(\log n\),有极低概率成为大倒霉蛋。

什么是平衡树

平衡树是一种数据结构,这种数据结构是以二叉搜索树为主体,但是可以实现插入删除等操作。

平衡树比较常见的形式有 Splay,Treap,目前我只会Treap

Treap分为有旋和无旋,无旋Treap又称为FHQ-Treap,核心在于用堆+二叉搜索树树确定树的形态,单次操作期望时间复杂度为 \(\log n\) 的。

具体证明不会。

FHQ-Treap采用分裂+合并的方式来处理子树的问题,因此很多操作会比较快捷,比如查询某个数的排名,直接按照这个值分裂,取出小的那部分,记录树的大小即可。

平衡树内的值可以按照权值或者排名排序,左边的一般维护小的,右边一般维护大的。

怎么写平衡树

写平衡树首先有一个点就是要如何维护成一个堆,常见方法就是直接摇随机数,然后再合并是比较两个权值来确定谁在上面。

核心还是在于怎样实现分裂和合并操作

直接上代码

分裂:

pair<int,int> split(int p,int v){
    if(!p)return {0,0};
    if(val[p]<=v){
        pair<int,int> tmp=split(rs[p],v);
        rs[p]=tmp.first;
        pushup(p);
        return {p,tmp.second};
    }
    else {
        pair<int,int> tmp=split(ls[p],v);
        ls[p]=tmp.second;
        pushup(p);
        return {tmp.first,p};
    }
}

合并:

int merge(int u,int v){
    if(!u||!v)return u|v;
    if(c[u]<c[v]){
        rs[u]=merge(rs[u],v);
        pushup(u);
        return u;
    }
    else {
        ls[v]=merge(u,ls[v]);
        pushup(v);
        return v;
    }
}

平衡树也可以使用懒惰标记进行修改,也可以上传某个值,对左右子树内容与这个节点进行合并

这么说平衡树可以完成大部分线段树的内容,只是可以用线段树做的偏用平衡树,太有病了

反正这样其实差不多就水完了,毕竟数据结构,实现1的功能就那么点,重在理解

而我明显不想证明时间复杂度

posted @ 2025-11-28 09:53  huhangqi  阅读(0)  评论(0)    收藏  举报
/*
*/