笛卡尔树的妙用

前言

笛卡尔树,它和treap是非常类似的,每个节点拥有两个值,key值和val值。key值是这个节点本身的大小值,在一颗treap中满足二叉查找树的性质,而val值则是一个随机值,学过treap的同学都知道,这个val值是拿来使得树的层高是期望log的,val值满足堆的性质,这里以小根堆为例讲解(当然大根堆不会有任何问题)。

应用

一般笛卡尔树都被用来建一颗treap,复杂度为O(n)的,n表示插入的元素个数。
而暴力插入的话是O(n log n)的。
这里需要讲清楚的是,笛卡尔树建树,插入的元素必须保证key值递增,而val值是可以乱的,许多博客里没有讲,这里必须要强调一下。

实现

我们维护笛卡尔树的极右链,就是根,根的右儿子,根的右儿子的右儿子.......
放在一个栈里,栈底是根,这样很显然从栈顶到栈底,val值是不断变小的。
每当我们进入一个新的节点,我们从栈顶开始找,当找到第一个节点的val值比我小,那么我必须得是它的儿子,而我的key值又比他大,所以我作为它的右儿子,而原先它的右儿子key值比我小,所以作为我的左儿子,这样就维护了一个treap的性质,然后原来那些点变为了我的左儿子,所以就要从极右链中删掉,我加入到极右链中,这样每个点进栈一次,出栈一次,复杂度就是O(n)的,下面贴出具体的代码。

for (int i=1;i<=n;i++){
        read(key[i]),val[i]=rand();
        while (top&&val[i]<val[stack[top]]){
            rson[stack[top]]=last;
            last=stack[top];
            lson[i]=stack[top];
            top--;
        }
        if (top) rson[stack[top]]=i;
        stack[++top]=i;
    }

以上就是笛卡尔树线性建treap的全部过程,希望对大家的学习有帮助

转载于:https://www.cnblogs.com/Michael-Li/p/8734961.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值