点分治&动态点分治

点分治

0x00 简介

  • 有时候我们会遇到一类问题
  • 这一类问题要求我们回答一些关于树上的链的问题
  • 比如是否存在某个链满足某个性质或者求某个性质最大的链
  • 而且链上的信息可以合并——即一条链可以拆成两条链分别计算并且合并
  • 比如说链上权值和,链上最大值等等
  • 我们就可以用树分治的思想解决这类问题
  • 树分支有点分治和边分治两种,一般好像没人写边分。。

0x01 点分治思想

  • 我们固定一个根节点,考虑把树上所有链分成两类
  1. 不经过根节点
  2. 经过根节点
  • 我们发现不经过根节点的是一个递归的子问题,所以只需在每棵子树中递归处理即可
  • 那么我们只需考虑经过根节点的路径即可
  • 因为每条链至少经过一个节点,所以它至少会在一次分治中被处理到,而且一条链一旦被处理,在接下来的分治中都不会再出现(链上的某个点被剔除了)
  • 所以我们既不会计重也不会计漏
  • 那么我们考虑如何处理经过某个节点的链
  • 逐个处理所有子树,遍历这棵子树,用之前子树的信息更新答案,然后把这个子树的信息加入统计的子树的信息中
  • 这样事实上每个点会被处理O(递归层数)次,如果我们希望复杂度合理,就需要最小化递归的层数
  • 如果每次都把当前子树的重心作为根节点,容易得知递归层数是log级别的,这样复杂度就是nlogn
  • 搞完啦

0x02 动态点分治

  • 请去写两道题或者看下代码理解一下点分治再来看这个
  • 我们发现点分治的结构构成了一棵树,即上一层的重心和下一层的重心之间是父亲和儿子的关系,虽然这棵树长得和原来不一样,我们把这个树叫做点分树
  • 然后如果我们要做单点修改,点分树上对应的修改是一条某个节点到根的链
  • 由于点分治的层数是log级别的,容易得知这条链最长也是log
  • 所以我们可以暴力的爬这条链进行修改,同时更新答案
  • 此时可能需要什么给每个点维护两三个堆之类的暴力做法
  • 具体实现看代码
许愿弥生改二
原文地址:https://www.cnblogs.com/LoveYayoi/p/6745500.html