树分治

点分治

思想

回想序列分治的做法:递归统计两个区间,在统计跨两个区间的贡献

对应到树上也类似:找一个分割点,统计子树的贡献,再统计跨子树的贡献

由于路径都可以被某一级重心统计到,所以点分治长于做路径统计问题

找树的中心

树的中心:以它为根时的最大子树最小的点

处理方式:开全局变量maxsiz,dfs找出每棵子树的大小(父亲的子树大小用sumsiz[v]计算)

目的:使每次分割的子树尽量小

流程

1、找到树的中心;

2、统计子树中和该点有关的量;

3、删除该点,分裂出若干棵树,对每棵树做一遍点分治;

为什么时间复杂度是O(nlogn)

对每棵树处理次数为n,siz1,siz2,...,sizk

总和为n+np1+np2+...+npk

大约和调和级数同阶,所以为O(nlogn)

P6626 [省选联考 2020 B 卷] 消息传递

点分治模板题

开桶,对子树内点,用桶统计子树外(过树的中心)贡献,对中心,直接统计子树贡献

进子树前记得去掉该子树的贡献

由于每个点都会成为中心,可以统计完全

P5984 [PA2019]Podatki drogowe

拼凑型题目,对于熟悉的人来说没有难处

1、路径第k大:二分答案+点分治计数

2、大数比较:主席树+哈希

3、发现值域过大,考虑在路径集内二分

4、发现路径集找权值中位数比较困难,考虑随机找一条权值在l,r之内的路径来做(随机二分)

5、

点分树

带修改的点分治,支持在线

点分治过程中,上一级重心向下一级连边,形成一棵有根树

性质:

1、树高O(logn),一些看似暴力的东西也可以直接存(如每个点存储该子树全部信息,这是O(nlogn)的)

2、在点分上,LCA(x,y)一定在原树中x,y的路径上

P6329 【模板】点分树 | 震波

对每个点开深度线段树存子树权值,暴力跳fa[]统计即可

对于要刨掉的x所属子树p,再开一棵线段树维护子树pfa[p]的距离

边分治

把重心换成边即可,记得单点度数过大时要拆点

P4565 [CTSC2018]暴力写挂

一个常见思路:多树统计,用虚树DP

路径问题,考虑点分治或边分治,这里使用边分治

统计左子树和右子树之间的最大权,发现原树的depth(LCA(x,y))不好处理,考虑对贡献进行转化

depth(x)+depth(y)(depth(LCA(x,y)+depth(LCA(x,y)))

=12dist(x,y)+12(dep(x)+dep(y))depth(LCA(x,y))

此时,原树的贡献可以完全放入x,y两个点内(12(dis[x]+dep[x])),将它们挂到虚树上,DP可得答案

时间复杂度O(nlog2n)

细节

1、为什么不用点分治?

点分治会产生若干棵子树,虚树DP很难O(n)解决

2、建虚树时存的lca,不要算它的权值

3、猜猜我调了3h+,发现问题在哪,原来是fa[N][20]倍增数组开小了啊,我tm真是个sb

posted @   Zhone_lb  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示