笛卡尔树
前言
发现自己居然没有写过笛卡尔树的构建的总结。。
正文
笛卡尔树的概念
待补。
笛卡尔树的构建
我们通过不断维护“最右链”来构造笛卡尔树,也就是每次笛卡尔树的最右链(当前栈)一定是单调递减/增的,然后如果有弹栈操作,我们就把这个节点作为我们当前末尾的左儿子,弹完后这个节点作为当前栈底的右儿子,成为新的最右链的底端。
代码如下:
#include<bits/stdc++.h>
using namespace std;
template <typename T>
inline void read(T &x){
x=0;bool f=false;char ch=getchar();
while(!isdigit(ch)){f|=ch=='-',ch=getchar();}
while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();}
x=f?-x:x;
return ;
}
template <typename T>
inline void write(T x){
if(x<0) x=-x,putchar('-');
if(x>9) write(x/10);
putchar(x%10^48);
return ;
}
#define ll long long
const int N=1e7+5;
int n,m,a[N],ls[N],rs[N],Root;
ll Ans1,Ans2;
int sta[N],top,siz[N],tmp;
signed main(){
read(n);
top=0;
for(register int i=1;i<=n;i++){
scanf("%d",&a[i]);tmp=0;
while(top&&a[sta[top]]>a[i]) tmp=sta[top--];
rs[sta[top]]=i;ls[i]=tmp;sta[++top]=i;
}
for(register int i=1;i<=n;i++) Ans1^=1ll*i*(ls[i]+1),Ans2^=1ll*i*(rs[i]+1);
write(Ans1),putchar(' '),write(Ans2);
return 0;
}
笛卡尔树的性质
当前节点是当前区间内的最值,左儿子是左区间的最值,右儿子是右区间的最值。(当然可以改造成多叉的)
笛卡尔树期望构造树高是 \(\log n\) 的。

浙公网安备 33010602011771号