笛卡尔树模板
定义:
笛卡尔树是一种二叉树,每一个节点由一个键值二元组\((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;
}