长链剖分总结

1|0长链剖分总结

长链剖分,顾名思义,就是按照链长(即深度)把树剖成若干条链。具体的,定义每个点的儿子中,子树深度最大的点是重儿子,不断跳重儿子形成的链也就是长链。

1|0长链剖分的性质:

1.从一个点向上跳长链的次数不会超过n次。

证明:考虑每跳到一条新的链上,这条链一定比前一条链长,而最坏情况下,才有长链长度分别为1,2,3,n,因此最多不会跳超过n条长链。

2.任意一个点的k级祖先所在的长链的长度大于等于k

证明:如果k级祖先所在的链长度小于k,又因为这个点到k级祖先这条链已经长于原先的长链了,而这是不可能的,故任意一个点的k级祖先所在的长链的长度大于等于k

1|1长链剖分的应用

1|01.O(nlog⁡n)−O(1)求树上k级祖先

根据刚刚的性质,我们令k=k2,那么xk级祖先所在的长链长度不小于k,那么就可以知道xk级祖先在条长链上了,然后我们预处理出倍增数组和小于链长次祖先,询问时就可以做到O(1)了。

例题:

【模板】树上 k 级祖先

1|02.优化和深度有关的树形DP

思路类似dsu on tree ,每次从重儿子那里继承信息,再额外计算轻儿子的贡献。

例题:

1.CF1009F Dominant Indices

题意:给定一棵有n个节点的树,设d(x,k)为点x的子树内与x距离为k的点数,对于每个点,求出使d(x,k)最大的k中最小的一个。

思路:考虑一个O(n2)的DP,设fx,i表示x的子树里与x距离为i的点的个数,转移时fx,ify,i1。我们尝试优化,即先从重儿子那里继承信息,再把轻儿子的信息暴力合并上去。我们可以发现,如果只看重儿子的话,那么就相当于把fy错位对应上了fx,那我们就可以利用一种特殊的技巧,即动态分配DP数组的内存。具体来讲,我们为每条长链链顶申请长为链长的空间,然后链上的所有点共用这部分空间,即fy的起点是fu+1,那这样就可以把时间和空间都减到O(n)的量级。这时我们再考虑把轻儿子的答案,合并上来,这样的复杂度也是O(n)的,因为每一条长链只会被合并一次,而且每一次合并是O(len)的(len是链长),总共加起来就是O(n)的。这样我们就成功地把O(n2)优化到了O(n)

2.[POI2014]HOT-Hotels

题意:求树上选择两两距离相等的3个点的方案数。

思路:先考虑朴素DP。设fx,i表示点x的子树内与x距离为i的点的数量,gx,i表示x的子树内满足d(u,lca(u,v))=d(v,lca(u,v))=d(x,lca(u,v))+i的点对数量,因此有转移:

ansfx,i1×gy,i,ansgx,i+1×fy,i,fx,ify,i1,gx,i+1gy,i+fx,i+1×fy,i

可以发现,fx,gx可以像上一道题一样直接从fy,gy移一位得到,那自然也可以用动态分配内存来优化,只是注意gsonx=gx1意味着之前要多申请一倍空间。

3.[湖南集训]更为厉害

题意:多次询问,给定a,k,求树上满足dis(a,b)k,且a,b都是c的祖先的点对(b,c)的数量。

思路:这道题有114514种做法,之前用的是O(nlogn)的离线树状数组的做法,这里给出一个长剖的O(n)的做法。

首先考虑b不在a子树里的情况,这时b只能是a的祖先,那答案自然就是min(dep[x]1,k)×(siz[a]1)

然后就是ba子树里的情况,这时的贡献就是dis(a,b)ksiz[b]1,看起来这个东西也可以类似地维护,只是需要维护长链上的后缀和,这样转移时就可以直接错位继承了。复杂度O(n)


__EOF__

本文作者Xttttr
本文链接https://www.cnblogs.com/Xttttr/p/17262667.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   Xttttr  阅读(63)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示