笛卡尔树学习笔记
算法介绍
笛卡尔树是一种特定的二叉树数据结构,可由数列构造,在范围最值查询、范围top k查询(range top k queries)等问题上有广泛应用。它具有堆的有序性,中序遍历可以输出原数列。笛卡尔树结构由Vuillmin(1980)在解决范围搜索的几何数据结构问题时提出。从数列中构造一棵笛卡尔树可以线性时间完成,需要采用基于栈的算法来找到在该数列中的所有最近小数。——百度百科
笛卡尔树,类似于\(Treap\) ,每个节点由两个关键值\(val,w\)组成,其中\(val\)满足\(BST\)二叉查找树的性质,中序遍历升序,\(w\)满足堆性质。
两个关键值都是确定的,因此笛卡尔树可能并不平衡。
建树
主要通过优先满足\(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;
}
可以结合的算法
单考一个裸的笛卡尔树是不可能的。