笛卡尔树
笛卡尔树
定义
笛卡尔树就是一种二叉树。笛卡尔树的每一个节点由一个二元组
Treap 和笛卡尔树
Treap 是笛卡尔树中的一种,只不过 Treap 中的
完全随机。或者说,Treap 是平衡的笛卡尔树。
如图这颗笛卡尔树把下标作为
建树
考虑按照下标将点依次插入到当前的笛卡尔树中。那么我们每次插入元素必然在这棵树右链的末端。假设我们维护的时小根堆。那么我们不妨把右链看作一个单调递增的单调栈,去把当前点插入到合适的位置,把比他大的点就作为他的左儿子。
代码实现
int n, a[N];
int st[N], head; // 维护单调栈
int ls[N], rs[N]; // 存储每个点的左儿子和右儿子
int main() {
n = read();
for (int i = 1; i <= n; i++) {
a[i] = read();
}
for (int i = 1; i <= n; i++) {
int k = head;
while (k && a[st[k]] > a[i]) k--; // 维护单调栈
if (k) rs[st[k]] = i;
if (k < head) ls[i] = st[k + 1];
st[++k] = i;
head = k;
}
return 0;
}
例题
根据给出的数组构建一颗笛卡尔树(二叉搜索树+小根堆)。设
分别表示节点 的左右儿子的编号(若不存在则为 )。一行两个整数,分别表示 和 。
#include <bits/stdc++.h>
#define int long long
using namespace std;
int read() {
int x = 0; char ch = getchar();
while (ch < '0' || ch > '9') ch = getchar();
while (ch >= '0' && ch <= '9') {
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return x;
}
const int N = 1e7 + 10;
int n, a[N];
int st[N], head;
int ls[N], rs[N];
signed main() {
n = read();
for (int i = 1; i <= n; i++) {
a[i] = read();
}
for (int i = 1; i <= n; i++) {
int k = head;
while (k && a[st[k]] > a[i]) k--;
if (k) rs[st[k]] = i;
if (k < head) ls[i] = st[k + 1];
st[++k] = i;
head = k;
}
int ans1 = 0, ans2 = 0;
for (int i = 1; i <= n; i++) {
ans1 ^= i * (ls[i] + 1);
ans2 ^= i * (rs[i] + 1);
}
printf("%lld %lld\n", ans1, ans2);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】