笛卡尔树 学习笔记
前置知识
二叉查找树,堆,单调栈
引入
笛卡尔树是一种二叉树,每一个节点由一个键值二元组
上面这棵笛卡尔树相当于把数组元素值当作键值
竞赛中使用笛卡尔树时,常用数组下标作为二元组的键值
用栈构建笛卡尔树
过程
我们考虑将元素按下标顺序依次插入到当前的笛卡尔树中。那么每次我们插入的元素必然在这棵树的右链(右链:即从根节点一直往右子树走,经过的节点形成的链)的末端。于是我们执行这样一个过程,从下往上比较右链节点与当前节点
图中红框部分就是我们始终维护的右链:
显然每个数最多进出右链一次(或者说每个点在右链中存在的是一段连续的时间
NOTE
实际上,Treap 是笛卡尔树的一种,只不过 Treap 中
C++ 实现
cpp
// stk 维护笛卡尔树中节点对应到序列中的下标
for (int i = 1; i <= n; i++) {
int k = top; // top 表示操作前的栈顶,k 表示当前栈顶
while (k > 0 && w[stk[k]] > w[i])
k--; // 维护右链上的节点
if (k)
rs[stk[k]] = i; // 栈顶元素.右儿子 := 当前元素
if (k < top)
ls[i] = stk[k + 1]; // 当前元素.左儿子 := 上一个被弹出的元素
stk[++k] = i; // 当前元素入栈
top = k;
}