笛卡尔树


笛卡尔树的前序遍历的 \(pos\) 值与原序列相同,且 \(val\) 值构成小根堆。

如何建树:从 \(1\)\(n\) 加节点,用单调栈维护最右链,每次插入时都不断弹出当前栈顶直至栈顶 \(fa\) 满足 \(val[i]>val[fa]\) ,记最后弹出的为 \(j\) ,则 \(fa\) 的右儿子为 \(i\)\(i\) 的左儿子为 \(j\).

//5854
#include 
#define int long long
using namespace std;

long long read()
{
	long long res=0,p=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-')p=-1; ch=getchar();}
	while(isdigit(ch)) res=res*10+ch-'0',ch=getchar();
	return res*p;
}

const int maxn=1e7+10;

int n;
int p[maxn];
int a[maxn][2];
long long ansl=0,ansr=0;

vector v;

signed main()
{
	n=read();
	for(int i=1;i<=n;++i) p[i]=read();
	for(int i=1;i<=n;++i)
	{
		int j=0;
		while(v.size()&&p[v.back()]>p[i]) j=v.back(),v.pop_back();
		if(v.size()) a[v.back()][1]=i;
		a[i][0]=j,v.push_back(i);
	}
	for(int i=1;i<=n;++i) ansl^=i*(a[i][0]+1),ansr^=i*(a[i][1]+1);
	cout<
ds