定义:
笛卡尔树是一种二叉树,每一个节点由一个键值二元组((k,w))构成,要求(k)满足二叉搜索树的性质,而(w)满足堆的性质
构建:
我们考虑按照键值(k)排序,然后一个一个插入到当前的笛卡尔树中(这样就保证了他一定满足二叉搜索树的性质),且每次我们插入的元素一定在这个树的右链(右链:即从根结点一直往右子树走,经过的结点形成的链)的末端,于是我们我们执行这样一个过程,从上到下比较右链节点与当前节点(u)的(w),如果找到一个右链上的节点(x)满足(x_w<u_w),就把(u)接到(x)的右儿子上,而(x)原本的右子树就变成了(u)的右子树,这样就可以保证堆的性质
显然每个数最多进出右链一次(或者说每个点在右链中存在的是一段连续的时间)。这个过程我们可以用栈维护,栈中维护当前笛卡尔树的右链上的结点。一个点不在右链上了就把它弹掉。这样每个点最多进出一次,复杂度(O(n))
code
int top = 0;
for (int i = 1;i <= n;i++){
int k = top;
while (k > 0&&a[st[k]] > a[i]) k--;
if (k) rs[st[k]] = i;
if (k < top) ls[i] = st[k+1];
st[++k] = i;
top = k;
}