笛卡尔树
笛卡尔树实际上就是对于多个二元组 \((k_i,w_i)\) 的一棵树,使其所有 \(k\) 值满足二叉搜索树的性质,且所有 \(w\) 值都满足小根堆的性质。
在构建时,对于右链上的元素,自底向上一定是 \(w\) 值由小到大的,且一定 \(k\) 值从小到大。
所以我们按 \(k\) 值从小到大排序,比并按顺序插入右链中。
假设我们轮到第 \(i\) 个元素插入,我们先找到在第一个右链中 \(w\) 值大于 \(w_i\) 的元素下标 \(j\) 。因为这棵树需要满足二叉搜索树的性质,所以我们将 \(j\) 以下的元素接到 \(i\) 的左子树上,并将 \(i\) 接到 \(j\) 的右子树上。
使用栈模拟即可。
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e7+10;
int n;
int st[N],top;
int p[N],ls[N],rs[N];
inline int read(){
int x=0;
char c='&';
while(!isdigit(c))c=getchar();
while(isdigit(c)){
x=x*10+c-'0';
c=getchar();
}
return x;
}
signed main(){
std::ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
n=read();
// cout<<n<<endl;
for(int i=1;i<=n;i++)p[i]=read();
for(int i=1;i<=n;i++){
int k=top;
while(k>0&&p[st[k]]>p[i])k--;
if(k)rs[st[k]]=i;
if(k<top)ls[i]=st[k+1];
top=k;
st[++top]=i;
}
int ans1=0,ans2=0;
for(int i=1;i<=n;i++){
ans1=ans1^(i*(ls[i]+1));
ans2=ans2^(i*(rs[i]+1));
}
cout<<ans1<<" "<<ans2;
return 0;
}