可并堆
可并堆:一种支持插入、删除、修改、删除任意一个元素、求
下面的只讲可并堆中的一种:左偏树。
左偏树是二叉树,但并不是完全二叉树。它满足两个性质:① 每个结点的权值都小于等于儿子。② 每个结点
什么是
再定义
容易发现,左偏树的高度实际上是
性质一:
性质二:若
可以用归纳法证明,发现最少的情况就是 $v$ 的子树是一颗高度为 $k$ 的满二叉树。
重要性质:从一个结点往右走,最多走
证明:结点
接下来我们看一下这些操作。
-
Merge,合并两颗左偏树。假设合并两颗左偏树的根是
,不妨设 (否则 一下),则令 为 , 为 返回的根结点。再判断如果 ,则交换 。记得返回此时的根结点
。时间复杂度是
的,因为每次递归都是往右走的,而往右至多会走 步,所以复杂度 。 -
Insert,插入一个数,就是和一个单独的结点 Merge。
-
Query,查询最小值,返回根结点即可。
-
Delete Min,删除最小值。把根结点的左右儿子合并。
-
Delete u,删除任意一个结点
,需要提前给出结点编号。合并 的左右子树,令 为合并后的新根结点,然后此时分两种情况。-
增加了,则看一下 是它父结点的左儿子还是右儿子。如果是左儿子,啥也不干;如果是右儿子,先判断是否已经比左子树的 大了,如果是,交换子树。然后再更新父结点的 。更新了父结点的
之后,再递归更新父结点的父结点,以此类推。 -
减少了,如果 是右儿子,更新父结点的 ,然后递归看一下父结点是左儿子还是右儿子,一路往上更新;如果 是左儿子,看一下要不要交换左右子树,交换了也要更新父结点,再一路往上更新。
删除任意一个结点需要额外记录这个结点的父亲是谁,是父亲的哪个儿子。
-
模板题。除了要套一个并查集快速查询所在左偏树的根结点,注意不要按秩合并。
这题和上一题极其相似,只是注意多个最小值优先删除编号小的,于是我们在 Merge 的时候看一下两个根如果值相等,让编号小的先上。
if (a[L].val > a[R].val)
swap(L, R);
变成
if (a[L].val > a[R].val || (a[L].val == a[R].val && L > R))
swap(L, R);
每一个结点开一个最小根左偏树,一开始每个骑士都记录在它
然后进行一次 DFS,到一个结点
此时所有儿子的左偏树存着所有打到结点
注意标记有两维:一维是乘法标记,一维是加法标记,和 线段树2 一样。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!