笛卡尔树学习笔记
1.定义
笛卡尔树是一种特殊的二叉树,同时满足小根堆和二叉搜索树的性质,笛卡尔树的每个节点有两个值(k,w),k满足二叉搜索树性质,w满足小根堆性质。Treap也是一种笛卡尔树
2.性质
-
如果k,w是分别两两不同的,那么笛卡尔树也是唯一的
-
对于一颗笛卡尔树,它的中序遍历是原序列a
-
在原序列中的区间[l,r]的最小值,是l,r的最近公共祖先
3.建树
3.1.栈构建
先将元素按键值k排序,再依次插入笛卡尔树中,那么每次我们插入的元素必然在这个树的右链(右链:即从根结点一直往右子树走,经过的结点形成的链)的末端,然后从下往上比较右链节点x与当前节点u的w,若找到某个节点满足
显然,每个点最多进出右链1次,所以可用栈维护,时间复杂度O(n)
3.2.代码
例题:【模板】笛卡尔树
https://www.luogu.com.cn/problem/P5854
#include<cstdio>
#define ll long long
using namespace std;
int n,a[10000007],s[10000007],ls[10000007],rs[10000007],top;
ll ans1,ans2;
void build()
{
for(int i=1;i<=n;i++)
{
int k=top;
while(k&&a[s[k]]>a[i]) k--;
// printf("%d %d\n",top,k);
if(k) rs[s[k]]=i;
if(k<top) ls[i]=s[k+1];
s[++k]=i;
top=k;
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
build();
for(int i=1;i<=n;i++)
{
ll x=1ll*i*(ls[i]+1),y=1ll*i*(rs[i]+1);
ans1^=x,ans2^=y;
// printf("%d %d\n",ls[i],rs[i]);
}
printf("%lld %lld",ans1,ans2);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律