【学习笔记】笛卡尔树
概述#
有若干二元组 ,笛卡尔树要求关于 满足二叉搜索树的性质,关于 满足堆的性质。
构建#
以要求 满足小根堆为例,使用单调栈维护当前的右链。
现将所有二元组按 升序排序,每次插入一个元素时不断弹栈找到第一个小于 的节点,并将当前节点作为其右儿子,将弹掉的部分作为当前节点的左子树右链。
for(int i=1;i<=n;++i){
int now=top;
while(now&&p[st[now]]>p[i]) --now;
if(now) ch[st[now]][1]=i;
if(now!=top) ch[i][0]=st[now+1];
top=now;
st[++top]=i;
}
这种构建方法可以线性建出 Treap 来减小常数。
应用#
由于左右子树独立且跨过根的区间最值一定是根,可以用来解决一系列最值问题。
(之前不会笛卡尔树,SA 建这样的结构都是对 建 Kruskal 重构树)
例题#
HDU-6305 RMQ Similar Sequence#
要求两序列笛卡尔树同构。
实数域内随机出两个数相等概率为 ,直接看作离散化后的排列,而随机出的每个数期望大小 ,因此每个序列期望和为 ,只需求出有多少合法排列,每个子树内根节点是最小值的概率是 ,累乘即可。
Luogu-P6453 COCI 2008-2009#4 PERIODNI#
发现最小值两侧的高处不受限制。
建出高度随深度递增的笛卡尔树,考虑 DP,设 表示 子树内放置 个棋子,且位置全部高于 的方案数。
转移枚举 表示分别有 个棋子来自左右子树且位置全部高于 ,有 个棋子放置在 之间,转移方程:
HDU-4125 Moles#
使 满足二叉搜索树, 满足小跟堆,建出笛卡尔树。求解使用 KMP 与括号序匹配。
HDU-6854 Kcats#
观察发现单调栈大小等价于笛卡尔树到根路径上经过右儿子的个数加 ,因此如果已知 序列,那么根应当在 出现的最后一个位置,左子树递归找 出现的最后一个位置,右子树递归找 出现的最后一个位置。
建出树后 DP 过程是:
对于一些 未知的情况,考虑一个区间 DP,设 表示区间 构成子树,且根的 值为 ,转移即:
参考资料#
- OI Wiki
作者:SoyTony
出处:https://www.cnblogs.com/SoyTony/p/Learning_Notes_about_Cartesian_Tree.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效