神秘数据结构:笛卡尔树
神秘数据结构:笛卡尔树
这是一种大家都听过名字但都没做过多少例题的奇怪数据结构。
但是今天研究一下NOI大纲,它好像要靠,算了,整吧
和其它维护信息的数据结构不太相同的是,它更多的是去支持数数,或者是决策,之类的。
笛卡尔树是啥
这是一种数据结构,可以把一堆形如 的点对放到二叉树上,使得:
- 只看 ,树的中序遍历有序,即满足二叉搜索树(Binary Search Tree, BST)性质(左小右大)
- 只看 ,这是一个二叉堆,大根/小根
它的性质非常优秀,可以支持一些跟最大值有关的问题,或者是插入删除之类的问题(记录插入删除时间)
咋建
以小根为例,大根就反一下。
我们先把 排一下序。
法1
考虑树的根。由堆的性质,这是原序列的最小值。由BST性质,我们可以递归解决两边。
然后就每次把最小值提起来变成根,左右分别处理接在下面就行了。这样就是 的,用线段树优化一下能做到
尽管这个方法没有下一个方法快,但它能帮助我们理解笛卡尔树的性质。
法2
线性!(如果保证 有序)
考虑增量法,每次枚举一个 看看怎么把它加进来
为了满足BST性质,我们的第一反应是不断的走右儿子(即,右链),然后把它接在这条链底部的右儿子。
实际上我们再想一下,我们其实可以在右链上找一个地方把它“插入”进来,同样满足BST性质。如下图:
即,对于原树右链上 到 的一条边,令 的右儿子为 ,然后 的左儿子再接到 ,这样就实现了把 “插入” 到右链。
由于(小根)堆性质,任意一条向下的链都是递增的。我们要把当前的点 插入进来,就要找一个 “中间位置”,即, 到 的边,满足: 而 。此时用上述的 “插入” 方法把 插进来,容易发现,即满足了BST性质,又满足了BST性质。
照理来说找这个位置应该用二分法,然而,我们可以用一个单调栈来暴力维护,由于每个数只会进出一次,所以总复杂度是线性的。
还有一个细节注意,就是 一来直接变成当前最小值,反 客 为 主,此时不但要清掉链,还要把根设置成 。
性质 / 事实
(以小根为例)
-
以 为根的子树是一段连续的区间 (由BST性质),且 是这段区间的最小值,且不能再向两端延伸使得最小值不变(即,这一段区间是极长的)
-
在 左右子树里任选两个点,两点间的区间最小值必定是
注:两个点都可以取 本身,此时的区间最小值仍是
-
间的区间最小值为:
-
若 是个随机排列, 是 ,则树高期望为 ,具体多少后面说
-
Treap是一颗笛卡尔树,它依靠性质4确保复杂度
——因此我们可以动态维护笛卡尔树!
来点题!
上面提到,笛卡尔树可以有效的解决一些和最大/最小值有关的问题,或者是和插入删除有关的问题
经典题:柱状图最大子矩阵
直接形式化描述吧,给一个数组 ,求
我们想到可以钦点最小值,然后看最小值等于它的最长区间。
区间限制在下标上,而最大值的限制在 上。容易想到,下标第一维, 值第二维,来一颗笛卡尔树。
由性质1,我们可以枚举笛卡尔树上的节点,然后最长区间就是子树大小,更新一下最大值即可。
复杂度:
当然,这题也可以直接单调栈做,本质是差不多的
TJOI2011 树的序
首先有一个明显的贪心:我们先把BST搞出来,然后在BST上贪心跑:先走小儿子,后走大儿子。很显然这样的贪心是对的,因为先走大儿子,在这一位上就输了,肯定不优。
问题在于如何建BST。更明确的说, 的 BST。
那我们建出来的树肯定对于 满足 BST 性质了。然后再想到,我们每次插一个新数,都会插在下面。所以这颗树上,下面编号大于上面。
所以对于编号来说,这颗树满足堆性质。
好,一个BST性质,一个堆性质,笛卡尔树,没了。即,以 建一颗笛卡尔树,就是 的 BST 了。
由于 无序,需要先把它排一下序,复杂度就是 了。
当然,这个 的常数小的可以,因为 std::sort
非常快!
总结:若发现了一个BST性质,一个堆性质,啪的一下想到笛卡尔树
SPOJ PERIODNI
bzoj2616
我们注意到,对于一段棋盘,真正有限制条件的只有下面那一段。对于上面,因为没法跨过来,所以可以随便放,无影响。
我们的问题又和最小值有关了,所以考虑笛卡尔树,小根的。
建出来树之后直接在树上考虑问题。设当前点是 。对于它左右两颗子树对应区间里的棋盘,我们划分成两块:最小值上面的那一块,称作 ;大家共有的最小值那一块,称作 。如下图,绿色线上面就是 ,下面就是 。
对于 ,问题相当于我们要选若干个位置,使得行列均不同。用组合数选出行与列都是啥,再配对,就行了。
而对于 ,问题就麻烦在如何把下面这一块去掉。经过一番思考,得到一个神秘方法:直接记 表示, 子树里,把 父亲的那一段长度切掉,然后放 个车车的方案数。
那对于当前的 ,我们直接把左右儿子的 做一个卷积(这里可以暴力卷,因为瓶颈不在这),就可以得到在 部分里选若干个的方案数了。
对于 ,我们需要选若干个行,列出来。假设当前有 行, 列供选择。容易发现,,,即子树大小。
假设我们要求 ,即一共选 个;在 部分选择 个。此时 部分选择 个,尽管不占据 部分的行,但占据掉了列。于是 部分的方案数为:
其中 是选出来的行与列配对的方案数。
然后我们再把 部分的方案数卷起来,就可以得到 了。
agc028B Removing Blocks
首先我们可以把它看成是,均匀随机一个删除顺序,求代价的期望,乘一个
我们发现,每次删一个位置,然后两边分开搞,和笛卡尔树建树过程非常的类似。把每个点的删除时间搞出来,删一个点就提它做根,然后左右两边接过来,我们发现,它是一个笛卡尔树。其中,下标满足BST性质,删除时间满足小根堆性质。
一个位置的贡献就是它在笛卡尔树上的点深度 (即,到根路径上多少个点)。我们相当于求它的期望深度,乘以它的权值,加起来,就是代价的期望(由期望线性性)
现在问题变成如何求随机排列构成笛卡尔树的期望深度。
, 表示 的祖先。
问题又变成, 是 祖先的概率。不妨令 , 同理。
想象一下笛卡尔树的结构,如果 要是 的祖先,那 这一段里面, 得是最小值——要不然切在中间就把 分在两颗子树里了。
现在问题又变成,随机一个排列,区间 中 位置是最小值的概率。
首先我们先选 个位置放在区间里,然后令 个位置随便排, 位置放最小值, 个位置再随便排,最后除以 就行了。推一波式子发现一堆东西都抵消了,最后概率为 。应该有其它妙妙理解,但是我只会瞎几把推。
同理。最后搞出来我们发现这是一个调和级数求和。设调和级数
然后再按上述做一波就好了。
同时,由于 和 是同阶的,我们也证明了随机排列的笛卡尔树的深度,期望是 的。
笛卡尔树上启发式合并/分裂
启发式合并大家熟悉,启发式分裂的意思就是,我枚举一个点 ,算跨过 的情况,然后两边分别处理。对于计算跨过 的情况,我看左右哪个子树小,我就按这个子树作为枚举的标准,另一颗子树里块速的做。和启发式合并类似,它的复杂度也是多一个 。
例题:hdu6701,洛谷4755
都是启发式分裂,统计一下跨过中间的答案,两边递归做就行。
hdu那个比较傻逼,而洛谷的那个还需要小小的去一下重。
代码:
动态维护笛卡尔树: ZJOI2012 小蓝的好友
说是动态的笛卡尔树,其实就他妈的是个treap
当然,treap就他妈的是个笛卡尔树,所以似乎怎么说都没问题
设资源点为“黑点”,其余为“白点”。那我们要数至少一个黑点的子矩阵数
注意到这个题的"至少一个"四个字,仿佛是把"容斥"二字写在了脸上,怎么想都得容斥,变成 “没有”
那现在的问题就是数白的
我们当然可以预处理,就是这个 有点大,不太能忍一下
那还有啥好办法呢,注意到 都挺小的,那要么枚举 ,要么枚举 了
后者相当于要考虑加入一个黑的,会减少几个白的。但又要考虑到其它的黑色的影响,似乎还要来一个 的容斥:算了吧
那考虑前者。一种常见的套路就是,我们枚举它的一条边界,算另外几条边界
这个套路在处理二维的最大子矩阵中也用到了,枚举一维,处理出“高度”,转化成上面说的柱状图最大子矩阵
形式化点说,枚举 表示限制子矩阵的下边界是第 行。同样考虑处理出“高度”,即, 表示 这个位置往上多少格才会碰到黑的。如果自己就是黑的,那么 。
考虑枚举子矩阵的左右边界 。此时的方案数就取决于高度,而这个高度不能超过 间每个位置的高度,于是只能是 之间的整数,方案数是 种
于是总方案数就是
和 有关,一看就笛卡尔树。
建一个小根的笛卡尔树。根据上面的性质我们知道,枚举一个点 ,在 的左子树中,选一个作为 ;在 的右子树中,选一个作为 ,则 区间最小值为 。同时, 都可以取 本身。
所以把式子转化成:
分别表示左右子树, 表示子树大小, 表示可以取 本身。
那对于一行的答案,我们就可以 的算了。
那总不能每行暴力的建个笛卡尔树吧,又变成 了,肯定不行。
考虑两行之间的树,变化其实很小。首先每个位置都 ,然后是,这一行为黑的位置直接标
也就是说,我们需要资瓷:
- 整体
- 单点修改
- 维护笛卡尔树
考虑如何维护笛卡尔树。我们要保持 BST 性质满足的情况下,调整堆性质。考虑到平衡树的旋转操作,可以保持 BST 性质不变。
于是我们用平衡树的旋转来调堆性质就行了。写出来一看,这好像就是个 treap。
那复杂度如何保证呢?注意到数据随机生成,就相当于 treap 里面的随机权值一样,能够保证期望复杂度是 的。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效