点分治
思想
回想序列分治的做法:递归统计两个区间,在统计跨两个区间的贡献
对应到树上也类似:找一个分割点,统计子树的贡献,再统计跨子树的贡献
由于路径都可以被某一级重心统计到,所以点分治长于做路径统计问题
找树的中心
树的中心:以它为根时的最大子树最小的点
处理方式:开全局变量\(maxsiz\),dfs找出每棵子树的大小(父亲的子树大小用\(sum-\sum siz[v]\)计算)
目的:使每次分割的子树尽量小
流程
1、找到树的中心;
2、统计子树中和该点有关的量;
3、删除该点,分裂出若干棵树,对每棵树做一遍点分治;
为什么时间复杂度是\(O(n\log n)\)?
对每棵树处理次数为\(n,siz_1,siz_2,...,siz_k\)
总和为\(n+\frac{n}{p_1}+\frac{n}{p_2}+...+\frac{n}{p_k}\)
大约和调和级数同阶,所以为\(O(n\log n)\)
P6626 [省选联考 2020 B 卷] 消息传递
点分治模板题
开桶,对子树内点,用桶统计子树外(过树的中心)贡献,对中心,直接统计子树贡献
进子树前记得去掉该子树的贡献
由于每个点都会成为中心,可以统计完全
P5984 [PA2019]Podatki drogowe
拼凑型题目,对于熟悉的人来说没有难处
1、路径第\(k\)大:二分答案+点分治计数
2、大数比较:主席树+哈希
3、发现值域过大,考虑在路径集内二分
4、发现路径集找权值中位数比较困难,考虑随机找一条权值在\(l,r\)之内的路径来做(随机二分)
5、
点分树
带修改的点分治,支持在线
点分治过程中,上一级重心向下一级连边,形成一棵有根树
性质:
1、树高\(O(\log n)\),一些看似暴力的东西也可以直接存(如每个点存储该子树全部信息,这是\(O(n\log n)\)的)
2、在点分上,\(LCA(x,y)\)一定在原树中\(x,y\)的路径上
P6329 【模板】点分树 | 震波
对每个点开深度线段树存子树权值,暴力跳\(fa[]\)统计即可
对于要刨掉的\(x\)所属子树\(p\),再开一棵线段树维护子树\(p\)到\(fa[p]\)的距离
边分治
把重心换成边即可,记得单点度数过大时要拆点
P4565 [CTSC2018]暴力写挂
一个常见思路:多树统计,用虚树DP
路径问题,考虑点分治或边分治,这里使用边分治
统计左子树和右子树之间的最大权,发现原树的\(depth(LCA(x,y))\)不好处理,考虑对贡献进行转化
\(\displaystyle depth(x)+depth(y)-(depth(LCA(x,y)+depth'(LCA'(x,y)))\)
\(\displaystyle =\frac 1 2 *dist(x,y)+\frac 1 2*(dep(x)+dep(y))-depth'(LCA'(x,y))\)
此时,原树的贡献可以完全放入\(x,y\)两个点内(\(\displaystyle \frac 1 2*(dis[x]+dep[x])\)),将它们挂到虚树上,DP可得答案
时间复杂度\(O(n\log ^2 n)\)
细节
1、为什么不用点分治?
点分治会产生若干棵子树,虚树DP很难\(O(n)\)解决
2、建虚树时存的\(lca\),不要算它的权值
3、猜猜我调了3h+,发现问题在哪,原来是\(fa[N][20]\)倍增数组开小了啊,我tm真是个sb
标签:路径,frac,分治,depth,子树,统计 From: https://www.cnblogs.com/zhone-lb/p/18522195