首页 > 其他分享 >左偏树学习笔记

左偏树学习笔记

时间:2023-04-22 17:23:54浏览次数:58  
标签:log int rx 笔记 学习 左偏 节点 dis

一、前言

左偏树是一种可以在 \(O(\log n)\) 内快速合并的堆式数据结构。
具体来说,
插入一个元素:\(O(\log n)\)。
查询最值:\(O(1)\)。
删除最值:\(O(\log n)\)。
合并:\(O(\log n)\)。
减少一个元素的值:\(O(\log n)\)。
同时它可以持久化。

二、定义

  1. 外节点:左儿子或者右儿子为空的节点。
  2. 一个节点 \(x\) 的距离 \(dis_x\) 代表节点 \(x\) 到其所在的子树内的最近的外节点的距离。特别地,如果 \(x\) 是外节点,\(dis_x=0\);如果 \(x\) 是空节点,\(dis_x=-1\)。

三、性质

  1. 左偏树满足小/大根堆的性质,即对于所有节点 \(x\),满足 \(v_x\le v_{lx}\) 且 \(v_x\le v_{rx}\),或者对于所有节点 \(x\),满足 \(v_x\ge v_{lx}\) 且 \(v_x\ge v_{rx}\)。
  2. 左偏树具有左偏性质,即对于任何一个节点 \(x\),有 \(dis_{lx}\ge dis_{rx}\)。

四、结论

  1. \(dis_x=dis_{rx}+1\)。这是因为根据定义,\(dis_x=min(dis_{lx},dis_{rx})+1\) 并且 \(dis_{lx}\ge dis_{rx}\)。
  2. 距离为 \(n\) 的左偏树一共至少 \(2^{n+1}-1\) 个节点,取等时它是满二叉树。这是因为根据定义,对于左偏树中的每一个节点 \(x\) 都满足 \(dis_{lx}\ge dis_{rx}=n-1\),否则 \(dis_{lx}\le dis_{rx}\),与性质矛盾。所以左子树的第 \(dis_{rx}+1=n\) 层的所有节点全部存在。递归地考虑,知道它至少是一棵满二叉树。所以至少 \(2^{n+1}-1\) 个节点。
  3. 一棵有 \(n\) 个节点的左偏树距离至多为 \(\lfloor log_2(n+1)\rfloor-1\)。可以由结论 2 推得。

五、实现

我们以根节点的编号指代一棵左偏树。这里我们假定维护的是小根堆,即全部求的是节点权值的最小值。

  1. merge(x,y):合并两个以节点 \(x\)、\(y\) 为根的左偏树,返回合并后的左偏树的根节点编号。这是左偏树最基础的操作。
    1. 首先,如果两棵树中有一棵为空,那么返回另外一棵树。
    2. 如果两棵树都非空,不妨假设 \(x\) 小于 \(y\),否则交换 \(x\),\(y\) 以避免讨论。
    3. 将 \(y\) 与 \(x\) 的右子树 \(r_x\) 合并。
    4. 返回时,如果回溯到节点 \(p\) 时, \(p\) 的右子节点 \(r_p\) 的距离 \(dis_{rp}\) 大于 \(p\) 的左子节点 \(l_p\) 的距离。 \(dis_{lp}\),那么这不满足左偏树的左偏性质。所以我们交换 \(p\) 的左右子树即可。
    5. 最后,由于节点 \(p\) 的距离可能发生改变,我们要更新 \(p\) 的距离,即令 \(dis_p\leftarrow dis_{rp}+1\)。
      总结:这样就可以合并两棵左偏树了。由于所有遍历过的节点都被更新了,所以这种修改后的依然是一棵左偏树。时间复杂度是原先的 \(dis_x\),是 \(O(\log n)\) 级别的。
  2. 求最小值:根节点的值,时间复杂度 \(O(1)\)。
  3. 删除最小值:删除根节点,合并根节点的左右子树,时间复杂度与合并两棵左偏树相同,为 \(O(\log n)\)。
  4. 插入新节点:容易知道一个点也是一棵左偏树,所以可以看做两棵左偏树的合并。时间复杂度也是 \(O(\log n)\)。
  5. 左偏树的建树:将所有节点作为左偏树放进先进先出的队列里,每次拿出队首的两棵左偏树,将它们合并后放到队尾。那么前 \(\frac{n}{2}\) 次合并的是距离为 \(0\) 的左偏树,然后 \(\frac{n}{4}\) 次合并的是距离为 \(1\) 的左偏树,……,然后 \(\frac{n}{2^i}\) 次合并的是距离为 \(i-1\) 的左偏树。总复杂度为 \(\frac{n}{2}\times O(1)+\frac{n}{4}\times O(2)+\frac{n}{8}\times O(3)+……=O(n)\)。
  6. 在左偏树上删除一个指定节点(并非删除值为 \(x\) 的节点,而是删除编号为 \(x\) 的节点)。
    1. 首先,我们将 \(x\) 的左子树、右子树合并,得到 \(x\) 的子树新的根节点 \(p\)。
    2. 如果 \(p\) 是全局的根节点,结束操作。
    3. 否则继续分类讨论,令 \(q\) 为 \(p\) 的父亲节点。
      1. 新树的距离为 \(dis_p\),如果满足 \(dis_q=dis_p+1\) ,那么结束操作。
      2. 如果满足 \(dis_q>dis_p+1\),那么 \(q\) 的距离应该更新为 \(dis_p+1\),而且如果 \(p\) 是 \(q\) 的左子节点,要交换 \(q\) 的左右子树。然后继续向上更新 \(q\) 的父亲节点。
      3. 如果满足 \(dis_q<dis_p+1\),那么 \(q\) 的距离应该更新为 \(dis_p-1\),而且如果 \(p\) 是 \(q\) 的右子节点,要交换 \(q\) 的左右子树。然后继续向上更新 \(q\) 的父亲节点。
        总结:这样就可以删除任何一个指定节点了。合并是 \(O(\log n)\) 的,向上更新是 \(O(\log n)\) 的,总复杂度 \(O(\log n)\)。
  7. 获得节点 \(x\) 所在的左偏树的根节点。直接向上跳,使用路径压缩即可。需要维护 \(rt_x\) 的值,在合并和删除时要更新。这个操作好像是均摊的,所以也许不可以可持久化。

六、例题

例 1.P3377 【模板】左偏树(可并堆)

点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch>'9'||ch<'0'){if(ch=='-')f=0;ch=getchar();}
	while('0'<=ch&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
	return f?x:-x;
}
inline void write(int x){
	if(x<0)putchar('-'),x=-x;
	if(x>=10)write(x/10);
	putchar(x%10+48);
}
int n,m,v[100010],l[100010],r[100010],d[100010],dl[100010],rt[100010];
int merge(int x,int y){
	if(!x||!y)return x+y;
	if(v[x]>v[y]||x>y&&v[x]==v[y])swap(x,y);
	r[x]=merge(r[x],y);
	if(d[r[x]]>d[l[x]])swap(l[x],r[x]);
	d[x]=d[r[x]]+1;
	return x;
}
int find(int x){
	return x==rt[x]?x:rt[x]=find(rt[x]);
}
int main(){
	n=read();m=read();d[0]=-1;
	for(int i=1;i<=n;i++)v[i]=read(),rt[i]=i;
	for(int op,x,y;m;m--){
		op=read();x=read();
		if(op==1){
			y=read();
			if(dl[x]||dl[y])continue;
			x=find(x);y=find(y);
			if(x!=y)rt[x]=rt[y]=merge(x,y);
		}else{
			if(dl[x]){puts("-1");continue;}
			x=find(x);
			write(v[x]);putchar(10);
			rt[x]=rt[l[x]]=rt[r[x]]=merge(l[x],r[x]);
			dl[x]=1;d[x]=l[x]=r[x]=0;
		}
	}
	return 0;
}

例 2.P4331 [BalticOI 2004]Sequence 数字序列

例 3.P3273 [SCOI 2010]棘手的操作

七、参考文献、资料

当然,不保证以下资料内容完全正确。我已经找到了一些错误,可惜这里太小,写不下。
题解 P3377 【【模板】左偏树(可并堆)】——雷哲涵
左偏树的特点及其应用——黄源河
左偏树——OI-WIKI

标签:log,int,rx,笔记,学习,左偏,节点,dis
From: https://www.cnblogs.com/qwq-qaq-tat/p/17341566.html

相关文章

  • 计组笔记:
    第一章计算机系统概述取自加以个人理解:https://blog.csdn.net/haojie_duan/article/details/112739522【复习提示】本章是组成原理的概述,考查时易针对有关概念或性能指标出选择题,也可能综合后续章节的内容出有关性能分析的综合题。掌握本章的基本概念,是学好后续章节的基础......
  • Python基础—conda使用笔记
    Python基础—conda使用笔记1.环境配置由于用conda管理虚拟环境真滴很方便,所以主要使用conda,就不单独去装Python了。1.1.Miniconda3安装Miniconda3官网下载地址:MinicondaMiniconda3清华镜像下载:清华镜像-Miniconda对于Windows系统:Miniconda安装跟正常的软件安装是一样......
  • Meerkat 2021 pulsar timing workshop 学习笔记(一)
    Thejoyofpulsars,byProfMatthewBaile,SwinburneUniversityofTechnologyhttps://www.youtube.com/watch?v=qG_hMzTCEX4&t=988s笔记不保证正确性(英语不行),最好观看原视频 1.引力天才们伽利略,第一个把望远镜指向天空的人,发现了木星有卫星开普勒,为行星绕太阳绕选给出了严......
  • python学习-学生信息管理系统并打包exe
    在B站自学Python站主:Python_子木授课:杨淑娟平台:马士兵教育python:3.9.9python打包exe文件#安装PyInstallerpipinstallPyInstaller#-F打包exe文件,stusystem\stusystem.py到py的路径,可以是绝对路径,可以是相对路径pyinstaller-Fstusystem\stusystem.py学生信息管理......
  • TS学习
    TypeScript在JS的基础上添加类型概念,一个变量生下来是什么变量就是什么变量 TS不能被JS解析器直接执行  xxx.ts不能直接执行使用ts编译成js TS增加了什么?1.TS可以使用变量类型tupleenuminterfaceabstractclass2.完全支持JS支持ES新特性3.添加ES不具备的......
  • 5.深度学习计算
    层和块importtensorflowastfimportnumpyasnpnet=tf.keras.models.Sequential([tf.keras.layers.Dense(256,activation=tf.nn.relu),tf.keras.layers.Dense(10)])X=tf.random.uniform((2,20))net(X)"""<tf.Tensor:shape=(2,......
  • SSM框架学习(1)
    一、Spring为什么要学Spring?Spring在学什么?Spring该怎么学?1、初识Springa.认识springb.spring发展史2、SpringFramework系统架构a.Spring系统架构图系统架构图讲究上层依赖于下层;第一核心大块1、CoreContainer表明Spring是一个用来管理对象的技术,即CoreContainer中装的就是对象;......
  • flink学习路线
    1传统架构2大数据架构和流式架构的演变工程3flink优势和不足4flink应用场景5flink基本架构6环境准备,运行环境和开发环境配置,建议使用java,兼容性好7flink编程模型:flink的数据集类型,编程接口,程序结构和数据类型4个维度进行分析。流式处理和批量计算。8flinktableap......
  • SkyWalking的学习之一
    SkyWalking的学习之一前言最近在学习应用调优诊断等内容.现在实际工作中实质上的拆分和微服务在售前阶段所以真正用到链路的地方比较少.但是人生都是要向前看的.想着一方面提高自己.一方面也是为了以后着想.在一个看不到未来和光的地方,要么离开,要么继续深入掘进.......
  • 如何配置一个用于深度学习的 GPU 服务器 [Ubuntu 18.04 LTS 为例]
    一、硬件配置CPUofInteli9-9980XE(18-core36-thread,@3.0-4.4GHz),RAMof128GB(DDR4),GPUofNVIDIARTX2080Ti*4(11GBGDDR6*4),andM.2NVMeSSDof1TB(/homewith256GBasswap),SATA3SSDof2TB(/ssd)andHDDof8TB*2(/dataand/proj).二......