笛卡尔树学习笔记

算法介绍

笛卡尔树(百度百科)

笛卡尔树是一种特定的二叉树数据结构,可由数列构造,在范围最值查询、范围top k查询(range top k queries)等问题上有广泛应用。它具有堆的有序性,中序遍历可以输出原数列。笛卡尔树结构由Vuillmin(1980)在解决范围搜索的几何数据结构问题时提出。从数列中构造一棵笛卡尔树可以线性时间完成,需要采用基于栈的算法来找到在该数列中的所有最近小数。——百度百科

笛卡尔树,类似于\(Treap\) ,每个节点由两个关键值\(val,w\)组成,其中\(val\)满足\(BST\)二叉查找树的性质,中序遍历升序,\(w\)满足堆性质。

两个关键值都是确定的,因此笛卡尔树可能并不平衡。

OI Wiki

建树

主要通过优先满足\(val\) ,维护一条右链。

每次新加入一个点时,找到右链上最浅的且\(w\)小于新点的点,将新点作为这个点的右儿子,这个点原先的右子树作为新点的左儿子。如果右链上的点的\(w\)都比新点大,那这个新点就作为新的根节点。

代码简洁优美好背

inline void build(){
	for(int i=1;i<=n;i++){
		int j=0;
		while(v.size()&&a[v.back()].v>a[i].v) j=v.back(),v.pop_back();
		if(!v.size()) rt=i;
		else rs[v.back()]=i;
		ls[i]=j;
		v.push_back(i);
	}
	for(int i=1;i<=n;i++) fa[ls[i]]=fa[rs[i]]=i;
	return;
}

可以结合的算法

单考一个裸的笛卡尔树是不可能的。

树形dp

分治

倍增

一些题目

模板

LuoguP5854

POJ2201

简单应用

HDU1506

分治

HDU6701

LuoguP4755

题解

未完待续❀

posted @ 2021-05-27 20:18  xxbbkk  阅读(77)  评论(0编辑  收藏  举报