介绍
笛卡尔树是一种非常特殊的二叉搜索树。每个节点有两个信息x和y。如果只考虑 x,它是一棵二叉搜索树,如果只考虑 y,它是一个小根堆。
实现
按照y升序插入
显然应该插入到一条极右链上
但为了维护x二叉搜索树的性质
对于右链上x>当前元素的点应该接到当前元素的左儿子上
从而保证两个性质均符合
实现可以用单调栈线性解决
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned ll
#define mid ((l+r)>>1)
const int N=1e7+100;
int n,m,tot;
int zhan[N],p[N],l[N],r[N],top,lst;
void insert(int x){lst=0;while(top&&p[zhan[top]]>p[x]){lst=zhan[top--];}if(top) r[zhan[top]]=x;if(lst) l[x]=lst;zhan[++top]=x;
}
int read(){int x=0,f=0;char c=getchar();while(c<'0'||c>'9') f=c=='-',c=getchar();while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48),c=getchar();}return f?-x:x;
}
int main(){n=read();for(int i=1;i<=n;i++) p[i]=read();for(int i=1;i<=n;i++) insert(i);ll res=0;for(int i=1;i<=n;i++) res^=1ll*i*(l[i]+1);printf("%lld ",res);res=0;for(int i=1;i<=n;i++) res^=1ll*i*(r[i]+1);printf("%lld",res);return 0;
}
/*
5 5
1 5 7 6 2
1 5 2
1 5 3
1 3 9
2 4 2
3 5 5
*/
应用
笛卡尔树可以用来解决RMQ问题
[l,r]的极值就是l、r对应结点的lca
不过为什么不用st表O1解决呢