笛卡尔树

笛卡尔树实际上就是对于多个二元组 \((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;
} 
posted @ 2024-04-25 12:59  Little_corn  阅读(10)  评论(0编辑  收藏  举报