有关树链剖分
数据结构,是一种以巧妙的存储方式和相应的数据处理规则来优化数据处理速度的工具;
树链剖分:一种处理树上链的相关信息的方法
——博主语;
今天将树链剖分啊,树链剖分好神啊!!
从前对她的印象:
“这题你用的什么?”某高三金牌学长
“树链剖分呀”某高二学长
“胡说,树链剖分是NOIP算法么,你要这样这样做...才像是NOIP选手啊”高三学长
。。。。。。
思路和实现:
对一棵树我们想很快的查询两点间的权值,怎么办呢?
记LCA再记点到根的距离即可;
如果,不止是这些,我们还想对她的某点甚至某链进行修改呢?
这怎么行,你当是线段树么!!
其实是可以的,我们今天讲链剖,她就是干这个的。
我们知道线段树能在线段上满足我们的需求;
于是我们试着把树简单的展成一个线段——用DFS序,然后维护线段树,线段树上的叶节点与原树上点一一对应;
然后发现不行。。。
DFS序中两点间的点并非她们路径;
然而,对某些点而言,DFS序中间隔的点就是她们路径(你应该明白);
(dfs序:指在dfs时各点被第一次到达的顺序)
基于这个关系;
我们可以在原来的线段树维护dfs序的设想上,添加“把任意链分解为可在DFS序线段树中查询的链,然后分别查询”的思路;
这也就是树链剖分啦!!
前提是我们得记录在dfs序中以点v为止的最长区间(记作X(v)),她满足是同一条链;
但dfs序是不定的,所以我们还得规定一种方便的dfs方式,最好还得高效;
这里引入轻重链的概念;
- 重边:对每个节点,她向子树最多的子节点连的边为重边,叶节点向自己连一条重边;
- 重链:连续的重边构成一条重链;
- 轻链(边):重边之外的边;
可以看出:
- 不存在不属于重链的点;
- 不存在连续的轻边;
- 每个点向下只连一条重边;
这样的话,我们可以维护使每条重链连续的dfs序,方法是dfs时对每个点优先跑重边;
可以第一遍dfs跑出深度dep(x),子树大小size(x),重边hline(x);
1 void dfs_1(int now){ 2 int j=first[now]; 3 while(j){ 4 if(!dep[x[j].to]){ 5 dep[x[j].to]=dep[now]+1; 6 fa[x[j].to]=now; 7 dfs_1(x[j].to); 8 size[now]+=size[x[j].to]; 9 if(hine[now]==now||size[x[j].to]>size[hine[now]]) 10 hine[now]=x[j].to; 11 } 12 j=x[j].next; 13 } 14 size[now]++; 15 }
第二遍dfs跑出个点在线段树的线段中的位置rank(x),和线段中b位置对应树上x点a(b)=x——也是dfs序;(这里点一下rank和a的关系)
1 void dfs_2(int now,int top_now){ 2 int j=first[now]; 3 top[now]=top_now; 4 a[++num]=now; 5 rank[now]=num; 6 if(hine[now]!=now) 7 dfs_2(hine[now],top_now); 8 while(j){ 9 if(dep[x[j].to]==dep[now]+1&&x[j].to!=hine[now]) 10 dfs_2(x[j].to,x[j].to); 11 j=x[j].next; 12 } 13 }
然后是查询的问题,
设top(x)为x所属重链的顶节点,dep(x)为x的深度,fa(x)为x的父节点
对于(u,v):
while(top(u)!=top(v))
if(dep(top(u))≥dep(top(v)))
find(top(u),u)
u=fa(top(u))
else
find(top(v),v)
v=fa(top(v))
if(u!=v)//只有在维护边,并把边权加在点上时,有这个限制
find(u,v)
每次,跳u,v两条重链中端点深度大的重链,然后把uorv指针转到重链端点父亲的重链上,重复该过程
效率:
为什么这样剖分快呢?
性质:
-
若(u,v)为轻边,则size(v)<size(u)/2
-
从某一点到根的路径上轻边的个数不大于O(logn)
-
从某一点到根的路径上重链不会超过O(logn)
性质一出自对重边的定义:若size(v)≥size(u)/2,她必然是一条重边;
性质二由性质一推得:由于size(v)<size(u)/2,故size(u)>2size(v),若点x到根的路径上轻边的个数大于O(logn),则size(root)>size(x)*2^logn>n;————这显然是不可能的;
性质三由性质二推得:每一条轻边分割出一条重链;
所以,这个树链剖分基于线段树,有了O(m*(log^2 n))的效率
例题:
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· .NET 适配 HarmonyOS 进展
· 用 DeepSeek 给对象做个网站,她一定感动坏了
· DeepSeek+PageAssist实现本地大模型联网
· 手把手教你更优雅的享受 DeepSeek
· 腾讯元宝接入 DeepSeek R1 模型,支持深度思考 + 联网搜索,好用不卡机!
· 从 14 秒到 1 秒:MySQL DDL 性能优化实战