首页 > 其他分享 >笛卡尔树

笛卡尔树

时间:2023-02-28 16:13:03浏览次数:48  
标签:结点 右链 笛卡尔 int il ri

笛卡尔树

总述

笛卡尔树是一种二叉树,每一个结点由一个键值二元组 \((k,w)\) 构成。要求 \(k\) 满足二叉搜索树的性质,而 \(w\) 满足堆的性质,如果笛卡尔树的 \(k,w\) 键值确定,且 \(k\) 互不相同,\(w\) 互不相同,那么这个笛卡尔树的结构是唯一的,构建的复杂度是\(O(n)\)的

构建

过程

将元素按照键值 \(k\) 排序。然后一个一个插入到当前的笛卡尔树中。那么每次我们插入的元素必然在这个树的右链(右链:即从根结点一直往右子树走,经过的结点形成的链)的末端。于是我们执行这样一个过程,从下往上比较右链结点与当前结点 \(u\) 的 \(w\),如果找到了一个右链上的结点 \(x\) 满足 \(x_w<u_w\),就把 \(u\) 接到 \(x\) 的右儿子上,而 \(x\) 原本的右子树就变成 \(u\) 的左子树。

由于每个数最多进出右链一次(或者说每个点在右链中存在的是一段连续的时间)。这个过程我们可以用栈维护,栈中维护当前笛卡尔树的右链上的结点。一个点不在右链上了就把它弹掉。这样每个点最多进出一次,复杂度 \(O(n)\)。

\(ps\) :\(Treap\) 就是笛卡尔树的一种,只不过 \(w\) 的值完全随机捏~

code

int n,p[N],stk[N],ls[N],rs[N];
il void build(int n){
    for(ri int i=1,t=0,tl=0;i<=n;++i,t=tl){
        while(t&&p[stk[t]]>p[i]) t--;
        if(t) rs[stk[t]]=i;
        if(t<tl) ls[i]=stk[t+1];
        stk[++t]=i,tl=t;
    }
    return;
}
AC·code
#include<bits/stdc++.h>
#define il inline
#define cs const
#define ri register
using namespace std;

namespace Q{
    il int rd(){
        ri int x=0;ri bool f=0;ri char c=getchar();
        while(!isdigit(c)) f|=(c==45),c=getchar();
        while(isdigit(c)) x=x*10+(c^48),c=getchar();
        return f?-x:x;
    }
    il void wt(long long x){
        if(x<0) x=-x,putchar(45);
        if(x>=10) wt(x/10);
        return putchar(x%10|48),void();
    }
} using namespace Q;

cs int N=1e7+5;
int n,p[N],stk[N],ls[N],rs[N];
long long las,ras;

il void build(int n){
    for(ri int i=1,t=0,tl=0;i<=n;++i,t=tl){
        while(t&&p[stk[t]]>p[i]) t--;
        if(t) rs[stk[t]]=i;
        if(t<tl) ls[i]=stk[t+1];
        stk[++t]=i,tl=t;
    }
    return;
}

signed main(){
    n=rd();
    for(ri int i=1;i<=n;++i) p[i]=rd();
    build(n);
    for(ri int i=1;i<=n;++i){
        las^=1ll*i*(ls[i]+1);
        ras^=1ll*i*(rs[i]+1);
    }
    wt(las),putchar(32),wt(ras);
    return 0;
}

标签:结点,右链,笛卡尔,int,il,ri
From: https://www.cnblogs.com/windymoon/p/17164659.html

相关文章

  • 动态笛卡尔树
    这里讲的动态笛卡尔树的问题指的是你要对一个序列单点加值并维护笛卡尔树的形态信息。由于具有严格偏序关系的数列对应的笛卡尔树唯一,我们只需要像维护Treap一样单点上......
  • 【YBT2023寒假Day12 B】仰望星空(DP)(线段树)(笛卡尔树)
    仰望星空题目链接:YBT2023寒假Day12B题目大意有一个n*n的网格,第i列下面的ai个点都是障碍。然后又一些不是障碍的地方有特殊点,删掉它有费用。要你用最小费用使得......
  • 为笛卡尔积运算而生的Reduce(Excel函数集团)
    我要是没记错,Reduce这词是减少的意思,可是当他作为Excel函数出现时,我真没看出哪里Reduce了……好吧,其实可以换种理解,缩减了嵌套(帮助里写的是“将数组缩减为累计值)。来来来......
  • left join(左连接)、right join(右连接)、full join(全连接)、inner join(内连接)、cr
    (1)leftjoin(左连接)在两张表进行连接查询时,会返回左表所有的行数据,右表中返回只返回和左表匹配的数据,没有的显示为Null。(2)rightjoin(右连接)在两张表进行连接查询时,会返......
  • 笛卡尔树学习笔记
    笛卡尔树下文的资料多摘自OIWiki性质笛卡尔树是一种二叉树,每一个节点都由一个键值二元组\((k,w)\)构成。要求\(k\)满足二叉搜索树的性质,而\(w\)满足堆的性质。如......
  • 笛卡尔树
    这篇文章有一部分是2021年写的,当时完全没有理解笛卡尔树的本质。笛卡尔树就是最值分治的搜索树。所以最容易的构建笛卡尔树的方式为:intget(intl,intr){ //返回[l......
  • 连接查询-笛卡尔积
    多表查询,当查询字段来自多个表笛卡尔积现象:表一有m行,表二有n行,结果=m*n行发生:没有有效的连接条件如何避免:赋予有效的连接条件分类:年代分类:sq192标准只支持......
  • 【数据结构】笛卡尔树
    把一个数组的元素,从左到右插入笛卡尔树,可以用栈O(n)地构建出来。笛卡尔树上的节点满足堆的性质(小根堆就是一个节点小于其两个子节点的权值)。所以用这个方式扫描出的笛卡尔......
  • MySQL的多表查询(笛卡尔积原理)
    先确定数据要用到哪些表。将多个表先通过笛卡尔积变成一个表。然后去除不符合逻辑的数据(根据两个表的关系去掉)。最后当做是一个虚拟表一样来加上条件即可。 注意:列名最好......
  • 笛卡尔树讲解
    前言笛卡尔树算是比较基础的数据结构了,但需要笛卡尔树的题目较少,且很多笛卡尔树的题都可以用其他解法解决,所以这个算法并不算的上热门,然而就在前天晚上,CF1748E这道......