点分治的理解与适用范围
点分治 被归到 数据结构 一章必然存在其原因,我们已知常用的类似 线段树 或者 树状数组 这些都可以实现 区间 上的维护,然而点分治 虽然是在 树 上进行的,但并非完全是图论,因为 点分治 也能维护区间的一些特性,只是由“序列上的区间”转化为了“树上两点之间的路径”。同时,这一过程需要是静态的而不能进行修改。
假设有一个由带边权的无向图构成的树,点 xxx 到点 yyy 路径上边的权值之和称为这两个点之间的距离,问长度不超过 kkk 的路径有多少条。如果用很 暴力 的方法是不是要从每个点出来跑一边图啊,那么是不是复杂度很爆炸,然而点分治可以用 O(NlogN)O(NlogN)O(NlogN) 的时间复杂度解决这个问题:
假设我们指定 ppp 节点为这个数的根,那么树上的路径可以分为两类:
1.1.1. 经过根节点 ppp ;
2.2.2. 包含于 ppp 的一棵子树中,即“不经过根节点”。
然而针对第二种情况,我们显然可以通过 递归 使其变成一个子问题,然后我们就处理时候就相当于在对链处理了。
比如这样的一条链:

我们是不是可以设置一个根节点(这里假设 333 为根节点),我们把这个图看做两部分,分别为 5−4−35 - 4 - 35−4−3 和 3−2−13 - 2 - 13−2−1 ,然后我们注意到只需分别讨论出这两部分的边的特质,就可以合在一起算了。
如果再加上一条链变成

我们同样以点 333 作为根节点,然后跑这个图,假设先跑了 3−2−13 - 2 - 13−2−1 这边,我们是不是可以把其中的答案先存到一个 vector 里面,然后再跑 3−4−53 - 4 - 53−4−5 这条边,将其中的长度和 vector 中的数据匹配组合,然后再存入 vector 中,然后再跑 3−6−73 - 6 - 73−6−7 这条边并将其中的长度和 vector 中已经存的路径长度进行匹配计算贡献。因此对于一次这样的操作,我们每个点都只会访问一遍,时间复杂度为 O(N)O(N)O(N) 。
现在考虑为什么选用点 333 来做根节点呢?因为点 333 是这个 树的重心 。我们考虑为什么要用 重心 作为根节点,比如假设我们现在要处理的 树 是一条 链 ,我们随便找了一个点,比如说是点 111 
是不是后面的还是一条链,还是要每个点当成根节点来跑一遍。可是如果我们选择了点 333 作为根节点,
那么是不是只需要再以点 222 和点 444 为根节点来跑这个图。那么是不是相当于我们如果每次以重心为根节点,这个 树/子树 都最多只会有

最低0.47元/天 解锁文章
3982

被折叠的 条评论
为什么被折叠?



