【基础操作】树分治详解(点/边分治)

时隔 $???$ 年,我又回来探望树分治了……

树分治是什么

先给一个很简单的例题

最简单的想法是枚举点对,然后 $O(1)$ 计算其距离(只需要知道它们的深度和它们的 $lca$ 的深度 就能算距离了,$lca$ 可以在预处理后 $O(1)$ 查询)。

这样是 $O(n^2)$ 的,直接被爆踩。

究其原因,我们发现必须要枚举出树上所有的简单路径。

那我们可不可以枚举每个点为中心,再暴力找是否有 两个不同儿子的子树中的点到当前点的距离和是 $k$(这两的话把这两个点的距离就是 $k$ 了)?

显然不行。如果一个点有很多个儿子,你甚至还得暴力枚举是哪两棵儿子子树中的点(因为两个点不能来自同一个儿子子树),也就是说这做法看起来是 $O(n^3)$ 的……

“我会差分!”

就是说,你可以不枚举是哪两棵儿子子树的点,而是直接把以当前点位根的子树中的所有点提取出来,两两组合。这样会多哪些情况呢?就是两个点在同一儿子子树的情况。我们对于每个儿子 减掉它的子树中的点两两匹配的情况就行了。

由于每个儿子最多被减一次,所以复杂度就降了一维,看起来是 $O(n^2)$ 了。

然而到此为止,即使我们把所有路径拆成两半,用乘法原理统计满足条件的路径数,做法的总体复杂度还是 $O(n^2)$ 的,接着被爆踩。

(你问怎么卡这个做法?人造一个强大的菊花图就卡掉了……)

猜你喜欢

转载自www.cnblogs.com/scx2015noip-as-php/p/point_cdq.html