首页 > 其他分享 >笛卡尔树

笛卡尔树

时间:2022-09-27 20:36:20浏览次数:77  
标签:rs rson 笛卡尔 st 权值 节点

概念

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 这道题呢。

标签:rs,rson,笛卡尔,st,权值,节点
From: https://www.cnblogs.com/shaojia/p/15415540.html

相关文章

  • 笛卡尔树
    笛卡尔树是一种二叉树,每个节点有两个键值\(x,y\),一个满足BST,一个满足堆。上图:一个性质是如果键值确定那么笛卡尔树是唯一的。笛卡尔树如果暴力构造很简单:找到整个序列......
  • 通过迭代工具itertools.product快速得到多列表笛卡尔积(列表组合)
    1.核心代码importitertoolssubject=['我想','我要']action=['打开','关闭']target=['电视','冰箱','洗衣机']forresinitertools.product(subject,ac......
  • python itertools库 itertools.product() 用法 产生多个序列的笛卡尔积
    python itertools.product()用来产生多个序列的笛卡尔积,参数可两个或者多个序列,元组tulple,列表list,range生成的序列,集合set都可作为参数1importitertools2#par......
  • 【模板】笛卡尔树
    笛卡尔树是一种二叉树,每个节点\(i\)由\(\left(k_i,w_i\right)\)构成,其中,\(k\)满足BST的性质,\(w\)满足堆的性质。若\(k,w\)互不相同,则构成的笛卡尔树唯一;两......