笛卡尔树(Cartesian Tree)
笛卡尔树(Cartesian Tree)
1. 定义
根据序列构造的满足以下性质的树:
- 二叉搜索树性质(BST):keyls≤keyx≤keyrs,key 默认为下标。
- 堆性质:valx≤valls≤valrs.
2. 构造
- 如果有 key 作为第一关键字,则按 key 升序排序,否则默认下标为 key;
- 使用单调栈维护右链,按照 key 升序的顺序添加节点。
- 加入一个新节点 i 时,找到右链上第一个 valj≤vali 的节点,将 rsj 作为 i 的左儿子,i 作为新的 rsj.
const int N = 1e5 + 5;
int n, root, v[N], fa[N], ls[N], rs[N];
stack<int> stk;
void build()
{
for(int i = 1; i <= n; i++)
{
cin >> v[i];
while(!stk.empty() && v[stk.top()] > v[i])
ls[i] = stk.top(), stk.pop();
fa[i] = (!stk.empty() ? stk.top() : 0);
if(!fa[i]) root = i;
if(ls[i]) fa[ls[i]] = i;
if(fa[i]) rs[fa[i]] = i;
stk.push(i);
}
return;
}
3. 应用
3.1. 求区间最小值(RMQ)
建立小根笛卡尔树,区间 [a,b] 的最小值是 valLCA(a,b).
利用 BST 的性质可以快速求 LCA.
复杂度为树的深度,随机数据下为 O(nlogn).
int find_min(int a, int b)
{
int lca = root;
while(lca < a || lca > b)
{
if(lca < a) lca = rs[lca];
if(lca > b) lca = ls[lca];
}
return v[lca];
}
3.2. 求最小值范围
给定一个无序序列和一个下标,求对应的值是多大范围内的最小值。
- 建立小根笛卡尔树,下标 i 对应的区间为 i 的子树中最左边的点到最右边的点。
3.3. 最大矩形
求下图的最大矩形(n≤105):
- 建立小根笛卡尔树,每个点的贡献是 子树大小×深度.
4. 例题
4.1. P1350 车的放置
fi,j:在 i 的子树中放 j 个车的方案数。
fu,i=∑ij=0soni×j!(i−1j)(w−(i−j)j).
soni=∑ij=0(flc,j×frc,i−j).
在 n×m 的矩形中放 k 个车:Ckn×Ckm×k!.
望穿寂夜晨曦至,雄鹰展翅图九天。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】