Loading

笛卡尔树

笛卡尔树就是每个结点有两个值 val 和 key,其中 val 满足 BST 的性质而 key 满足堆的性质。treap 就是一棵笛卡尔树。
可以证明给定 val 和 key 的前提下笛卡尔树的形态是唯一的。
很明显借助于平衡树的知识我们能 \(O(n\log n)\) 进行构建。
但是,当给定的元素已经按照键值 val 排好序了,我们完全可以做到线性。方法如下。

首先,我们注意到由于 val 有序,我们每次插入的位置一定是右链末端。
于是我们有这样的算法:
每次插入一个元素的时候,从下往上与右链中的元素进行比较直到找到位置,然后把原来右链中的结点整体作为当前结点的左子树。
这个过程很明显可以用栈来模拟。注意到每个元素最多入栈一次,于是我们就做到了线性复杂度。

上图。框出的部分就是用栈维护的右链。


(图源自OI-wiki

luogu模板题核心代码:
(为了卡常手写了栈

for(int i=1;i<=n;++i)
{
    a[i]=read();
    pos[a[i]]=i;
    if(!top){st[++top]=a[i];continue;}
    int lasttop=0;
    while(top&&a[i]<st[top])lasttop=st[top--];
    if(top)rs[pos[st[top]]]=pos[a[i]];
    st[++top]=a[i];
    ls[pos[a[i]]]=pos[lasttop];
}
posted @ 2022-07-13 22:25  pjykk  阅读(45)  评论(0编辑  收藏  举报