笛卡尔树学习笔记

笛卡尔树是一种二叉树,一个序列 a[l:r] 的笛卡尔树大概是这样定义的:

  1. 找到最小元素(设为 a[i])作为树的根;

  2. 根的左子树是序列 a[l:i-1] 的笛卡尔树,右子树是序列 a[i+1:r] 的笛卡尔树。

当然,对于相等的最小元素,选哪个为根都行。举例如下:

1399631-20190214111926751-1855431752.png

其中序遍历就是原序列,并且其点权有小根堆的性质,两点之间的最小值就是 LCA 上的值。

笛卡尔树有一种 \(O(n)\) 的构建方法,基于单调栈。

大概是从前往后扫,扫到一个元素 \(a_i\) 的时候,利用单调栈找到它之前的第一个比它小的 \(a_j\)

  • 如果 \(j\) 已经有了右儿子 \(k\) ,那么 \(k\) 变成 \(i\) 的左儿子,然后再将 \(i\) 设为 \(j\) 的右儿子。

  • 否则直接将 \(i\) 设为 \(j\) 的右儿子。

然后你就造完了一棵笛卡尔树。

有什么用?

1399631-20190214112334828-541617456.png

例.如上图,给出 \(n\) 和从左往右每根柱的高度,求其包含的最大矩形。\(n\le 2\times 10^6\)

单调栈可以直接做,但是不重要。

建出笛卡尔树,求出其所有子树中,子树大小乘高度的最大值就是答案,复杂度 \(O(n)\)

一些题目

SP3734 PERIODNI - Periodni

IOI2018 meetings

还有一些不知道从哪里搜集来的杂题:

1.刚开始你有 \(𝑛\) 个序列,刚开始序列都是长度为 \(1\) 的。每次要你拼接两个序列,问每个序列的每个子区间的最小值的和。\(𝑛 ≤ 10^6\)

2.给出 \(n\),随机一个 \(1\)\(n\) 的排列 \({P_n}\),求 \(\sum_{i=2}^n|P_i-P_{i-1}|\) 的期望,对大质数取模。\(n\le 100\)

posted on 2020-02-07 01:44  Dreamunk  阅读(123)  评论(0编辑  收藏  举报

导航