[学习笔记]虚树

  很久没有写过虚树了,想要复习一下发现以前居然没有一篇记录虚树的博客,遂大惊,只能又自己去复习一下 \(\mathcal O(n)\) 建虚树,然后有了这篇博客......

虚树的出现

  对于某些树上问题,只涉及一些少量的关键的树上节点,并且这些关键节点的信息将在他们的 LCA 处进行合并(可能原本也不是在 LCA 处合并,不过你也可以通过乱搞变成在 LCA 处合并),而且 这种对于特殊点的处理需要进行多次,此时如果再对整棵树进行处理,显然浪费了很多时间,但稍微分析上述操作,实际上给只用到了所有特殊点和他们的 LCA,那么何不将其他节点忽略,只保留这些特殊点和边信息?于是这就有了虚树。

虚树的建立

  虚树的节点数是 \(\mathcal O(|S|)\) 的,其中 \(S\) 为特殊点集,一个上界是 \(2|S|-1\):有 \(|S|\) 个特殊点,而 LCA 的个数最多只有 \(|S|-1\) 个(这个得自己想想),并且我们希望虚树的形态和原树相差不远。

  建立虚树的流程:

  1. 将所有关键点按照 dfn 排序;
  2. 将相邻关键点的 LCA 求出,加入点集,至此得到虚树点集;
  3. 将点集按照 dfn 排序;
  4. 建立栈,将 dfn 最小的元素加入栈;
  5. 从第二个元素开始,按照 dfn 从小到大遍历点集:弹出栈顶所有不是当前节点祖先的元素,直到出现祖先后,将该节点的虚树父亲设为栈顶元素,再将当前元素加入栈;

  由于需要按照 dfn 排序,忽略 LCA 部分的话,总复杂度为 \(\mathcal O(|S|)\sim \mathcal O(|S|\log |S|)\),,至于 LCA,一般推荐使用 \(\mathcal O(n\log n)-\mathcal O(1)\) 的预处理 ST 表方法。

posted @ 2022-02-17 16:45  Arextre  阅读(76)  评论(2编辑  收藏  举报