最后一篇以前写的文章了,
左偏树是一种实现简单的可并堆,可以在 logn 的复杂度下面完成优先队列的插入,删除,合并操作。
这就是一颗左偏树啦 蓝色是该节点的 dist
结构体定义
1 | struct Node{ |
我们定义左偏树的外界点为,一个左子树为空或者一个右子树为空的结点,结点的 dist 为它到它子树内外节点的最短距离。一个左偏树在满足堆的性质的前提下还应该满足它的右子树的 dist 不大于它的左子树的 dist。由此,我们可以得出其他一些性质。
当前结点的 dist 为右子树 dist 的长度+1
若左偏树根节点的 dist 为一定值,则节点数最少的左偏树是一颗完全二叉树,并且为满二叉树
由上一条性质,可以知道根节点 dist 为 n 的左偏树,最少含有 2n+1−12n+1−1 个结点
一个有 n 个结点的左偏树,根节点距离最大为|log2(n+1)|−1|log2(n+1)|−1
左偏树的操作(最大堆)
递归合并
如果有一颗树为空,返回另一棵树
否则,就将根节点键值较大树的右子树和根节点键值较小树合并
如果合并后破坏了左偏树的性质(左子树 dist<右子树 dist)
交换根节点的左右子树
更新根节点的 dist 值
1 | int merge(int x,int y){ |
插入
相当于和只有一个结点的树合并
1 | int insert(int x,int v){ |
堆操作
1 | int top(int x){ |
以上操作都以左偏树堆顶的编号代表这一刻左偏树
例题 hdu1512 左偏树加并查集的模版题,今年省赛的热身赛就是这题来着,当时乱搞搞出来了(数据太弱),重新用左偏树写一下。
1 |
|
并查集维护一个当前集合内优先队列的根节点 pqroot,合并的时候注意根的相关操作就 OK 了。