笛卡尔树是一种简易的Teap,可以快速处理出一个序列的最值的树状优先级,可以在DFS上按优先级遍历
时间复杂度和空间复杂度都为 O(N)
- 一次性建树
// 笛卡尔树,静态建树,区间最值跳转
struct CartesianTree {
int rt; // 根节点
pii ch[N]; // 左右儿子
int st[N]; // 单调栈
void build(int n, int p[]) {
rt = 0;
int t = 0;
for (int i = 1; i <= n; i++) {
// 决定了大于还是小于
while (t && p[st[t]] > p[i]) --t;
if (t) {
// 成为上一个点的右儿子
// 前一个点成为自己的左子节点
ch[st[t]].second = i;
ch[i].first = i - 1;
} else { // 自己作为根节点
ch[i].first = rt;
rt = i;
}
st[++t] = i;
}
}
} dika;
- 后续插入建树
// 笛卡尔树,静态建树,区间最值跳转
struct CartesianTree {
int rt; // 根节点
int tot; // 总个数
int p[N];
pii ch[N]; // 左右儿子
int st[N]; // 单调栈
int top = 0;
void insert(int val) {
// 决定了大于还是小于
p[++tot] = val;
int i = tot;
while (top && p[st[top]] > p[i]) --top;
if (top) {
// 成为上一个点的右儿子
// 前一个点成为自己的左子节点
ch[st[top]].second = i;
ch[i].first = i - 1;
} else { // 自己作为根节点
ch[i].first = rt;
rt = i;
}
st[++top] = i;
}
void build(int n, int a[]) {
rt = 0;
for (int i = 1; i <= n; i++) {
insert(a[i]);
}
}
} dika;