笛卡尔树的定义
笛卡尔树是一种二叉树,每一个结点由一个键值二元组 \((k,w)\) 构成。要求 \(k\) 满足二叉搜索树的性质,而 \(w\) 满足堆的性质。一个有趣的事实是,如果笛卡尔树的 \(k,w\) 键值确定,且 \(k\) 互不相同,\(w\) 互不相同,那么这个笛卡尔树的结构是唯一的。 ——OI wiki
笛卡尔树的构造
排序令 \(k\) 递增,每次插入一个新的节点,我们要使新插入的元素尽量靠右。
在这里我们假设要插入的点为 \((k_u,w_u)\)。
构造步骤:
1、维护一个从根节点开始,每次都向右儿子走的链。这条链可以用栈来维护
2、找到第一个链上的节点 \(x\) 使得 \(w_x\) 比 \(w_u\) 大。
3、i. 若 \(x\) 没有右子树,则将 \(x\) 的右儿子设置为 \(u\)。
3、ii. 若 \(x\) 有右子树,则让 \(u\) 替代 \(x\),并将 \(u\) 的左儿子设置为 \(x\)。
题目
模板题
代码示例
P5854代码~
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=10000009;
ll n,p[N];
ll stk[N],top;
ll l[N],r[N];
ll lans,rans;
void input(){
ios_base::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n;
}
void solve(){
for(ll i=1;i<=n;i++){
cin>>p[i];
if(top==0){
stk[++top]=i;
}
else if(p[stk[top]]<p[i]){
r[stk[top]]=i;
stk[++top]=i;
}
else{
while(p[stk[top]]>p[i]) top--;
r[stk[top]]=i;
l[i]=stk[top+1];
stk[++top]=i;
}
}
for(ll i=1;i<=n;i++){
lans^=i*(l[i]+1);
rans^=i*(r[i]+1);
}
cout<<lans<<" "<<rans;
}
int main(){
input();
solve();
return 0;
}
标签:入门,笛卡尔,ll,stk,键值,节点,top
From: https://www.cnblogs.com/lemon-cyy/p/17810383.html