点分治引入

点分治

前言

点分治,顾名思义,就是按照点去分治

其主要解决路径统计问题,例如两个点间距离不超过 \(k\) 的路径有多少条

这东西难起来还是挺难的

算法流程

上面我们也说到了,其主要解决的是路径统计问题,也就是树上满足某种条件的路径条数

给个情景,给定一个树,求长度为 \(k\) 的路径有多少条,\(n \le 10^5\)

  • 统计经过当前根的路径有多少条,只需要从前往后遍历每棵子树,将子树内的点加入桶

    遍历一棵子树时,设 \(dis_x\) 表示当前点到当前根的距离,在桶中查询有多少个 \(k - dis_x\) 将其加入答案即可

  • 将当前根删除,递归计算其子树

这样为什么可以不重不漏地统计到所有路径?

每条路径都由不少于两个点组成,而这些点中必然有一个点会被当做根,因为只有仅剩一个点时,这个点才不会被当做根统计答案,否则一定会选出一个根

每条路径只会在这时被统计到,并且在删除这个根后,这条路径就不可能再被统计到

这样的时间复杂度最劣为 \(O(n^2)\) ,当树为一条链时,就会变成 \(O(n^2)\)

所以我们需要自己选择选择哪个点做根,我们希望子树大小尽可能小,这样我们递归下去的时间复杂度就会更优

以树的重心为根时,所有子树的大小都不超过整棵树大小的一

因为重心满足我们所需要的性质,所以每次选择重心为根,每次子树大小至少减半,所以最多只会递归 \(O(\log n)\) 层,总时间复杂度为 \(O(n \log n)\) ,流程加个找重心作为根,其他不变

例题

点分治模板

聪聪可可

tree

race

digit tree

posted @ 2025-08-22 21:13  michaele  阅读(14)  评论(0)    收藏  举报