【学习笔记】笛卡尔树

定义

一棵树,每个点有两个权值,如果 a 权值满足 BSTb权值满足 heap,那么这棵树 就是一棵笛卡尔树

一般是对于一个序列建笛卡尔树

其实 Treap 就是一个笛卡尔树,不过笛卡尔树不平衡,同时一棵子树的中序遍历对应原序列中的一个区间

构造

O(n) 建树

考虑用单调栈维护最右边的一条链,和单调栈求每个点作为哪些区间的 RMQ 是类似的

代码:

for(int i=1;i<=n;++i){
    while(top&&a[st[top]]>a[i]) ls[i]=st[top--];
    if(top) rs[st[top]]=i;
    st[++top]=i;
}

例题

SPOJ3734

我们看到这个是一个直方图,而且形状不规则,就考虑到建一棵笛卡尔树

然后把题目转成在矩形中选点(笛卡尔树把直方图变成一个一个的矩形,然后就是放点了)

这里有个结论:n×m 的矩形中我们放 k 点,方案数为:Cnk×Cmk×k !

每个点都占一行和一列,所以两个组合数的乘积就是一个组合,排列数直接乘阶乘就好

然后是笛卡尔树上的 dp, 这里转移就考虑枚举在每一岔上放几个点就行了,最后加一加,乘一乘

ZJOI2012 小蓝的朋友

枚举每行作为矩形的最下面一行,设 wi 表示每列离当前行最近点的行号

这样子每行的答案可以表示为 i=1mj=immaxk=ijwk

根据笛卡尔树的重要性质一个子树的中序遍历是原序列里面的连续区间,那么每个点的贡献可以用左右儿子求

使用 fhq_treap可以进行笛卡尔树的分裂和合并,支持修改一个点的值,同时仍然维护笛卡尔树形态,本题直接套用即可

posted @   没学完四大礼包不改名  阅读(207)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示