笛卡尔树

概念

Link

笛卡尔树的节点各有两个权值,其中一个权值满足二叉搜索树的性质,另一个满足小(大)根堆的性质。

所以说 Treap 也是一种笛卡尔树

构造

知乎

以下均假设原序列元素两两不相同。

从左至右依次加入元素,维护当前笛卡尔树的右儿子链

\[root\to rson\to rson.rson\to rson.rson.rson\dots \]

至一个栈内。

设加入的节点为 \(x\)\(t\) 为当前笛卡尔树。

  1. 找到栈中最靠顶部的节点 \(y\) 使得 \(val[y]<val[x]\)

  2. 特判 \(y\) 为栈顶,直接 \(t[y].rson:=x\) 即可结束。

  3. 记栈中 \(y\) 的楼上为 \(z\)\(t[y].rson:=x,t[x].lson:=z\)

  4. 将栈中 \(y\) 之上的所有全部 \(pop\),再 \(push(x)\)

时间 \(O(n)\)

实战

模板

好像单调栈能做的,她都行。

P5854 【模板】笛卡尔树

以前这里贴了一个 \(O(n\log n)\) 的代码,放了好久,我该咋办。

现在改好了,\(O(n)\) 的。

/*
* Author: ShaoJia
* Last Modified time: 2022-09-27 18:20:41
* Motto: We'll be counting stars.
*/
#include<bits/stdc++.h>
using namespace std;
#define For(i,j,k) for(int i=(j),i##_=(k);i<=i##_;i++)
#define ll long long
#define N 10000005
char buf[1<<21],*p1,*p2;
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
inline int read() {
	int x=0,f=1;
	char c=gc();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
	while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=gc();}
	return x*f;
}
int n,a[N],ls[N],rs[N],s[N],st;
signed main(){
	n=read();
	For(i,1,n) a[i]=read();
	s[st=1]=1;
	int x;
	For(i,2,n){
		if(a[i]>a[s[st]]){
			rs[s[st]]=i;
			s[++st]=i;
		}else if(a[i]<a[s[1]]){
			ls[i]=s[1];
			s[st=1]=i;
		}else{
			x=s[st--];
			while(a[s[st]]>a[i]){
				x=s[st--];
			}
			rs[s[st]]=i;
			ls[i]=x;
			s[++st]=i;
		}
	}
	// For(i,1,n) cout<<ls[i]<<" "; cout<<"\n";
	// For(i,1,n) cout<<rs[i]<<" "; cout<<"\n";
	ll L=0,R=0;
	For(i,1,n){
		L^=1ll*i*(ls[i]+1);
		R^=1ll*i*(rs[i]+1);
	}
	cout<<L<<" "<<R<<"\n";
return 0;}

CF1220F Gardener Alex

vp 场上 \(O(n)\) 想法因为 sb 错误没调出来,被 Little09 \(O(n\log n)\) 压哨过暴踩。

发现其实就是要快速求出一个序列的任意前缀的笛卡尔树的深度。

发现我们可以直接在右链上维护每个节点左儿子的 \(\text{mxdep}\),压栈和弹栈的时候维护一下即可。

细节看代码吧,讲不清楚 /yun。

Link

P5654 基础函数练习题

咕咕咕,我还没 A 这道题呢。

P7244 章节划分

过了,但是咕咕咕。

CF1748E Yet Another Array Counting Problem

由于最大值位置定义为最左边的最大值,我们将每个位置 \(i\) 上的值改成二元组 \((val,-i)\),这样不存在相同的元素了,大小直接用 std::pair 比较即可。

不难发现题目相当于要求与 \(\{a\}\) 大根笛卡尔树结构相同的(长度 \(n\),值域 \(m\))序列有多少个。

然后就简单了,发现 \(n\cdot m\le 10^6\),树形背包做完了。

Code

posted @ 2022-09-27 20:20  ShaoJia  阅读(68)  评论(0编辑  收藏  举报