点分治
点分治适合处理大规模的树上路径信息问题。
- 求两点间距离为 k k k 的合法路径总和:使用扫描法 L L L, R R R
- 每次选择重心 p p p ,因为每一层的所有递归过程合计对每个节点处理 1 1 1 次,而点分治最多递归 l o g n logn logn 层,复杂度可以保证
- 求重心必须完整地遍历一次整个子树,但是 d i s dis dis 数组是可以通过 v e c t o r vector vector 存下来的(不超过 n l o g n nlogn nlogn 个元素),也就是说子树的信息完全可以用数据结构存下来(只要不超过子树大小),甚至可以接到父节点上
- 这就引出了点分树:将每次找到的重心与上一层的重心缔结父子关系,就可以方便地进行线段树合并等操作了
那么数据结构是干什么的呢?当然是计算 c a l c ( x ) calc(x) calc(x) 了。假设这个部分的时间复杂度是 O ( A ) O(A) O(A) ,总时间复杂度就是 O ( A n l o g n ) O(Anlogn) O(Anlogn) 。
这里可以把 c a l c calc calc 看成是一个静态的函数,所以可以一边递归一边计算。
点分治的含义是分治,也就是说分成若干个子问题,先将当前层的 c a l c calc calc 算出来,再分成若干个独立的子树分别求解。