虚树

55 阅读1分钟

算法介绍

对进行QQQQNN同阶)次的树上询问问题,每次选kik_i个点(ki\sum k_iNN同阶),每次对整棵树进行计算复杂度是O(QN)O(QN)的。但是可以建一颗虚树,只包含当前询问的kik_i个点和其他一些点(比如LCA),这样QQ次询问总的复杂度就是O(N)O(N)

建树方法:把当前询问的kik_i个点(下称关键点)按dfs序排序,用栈维护现在经过的链。先把根节点放进去,按顺序添加关键点uu,设栈顶节点为xx,次栈顶节点为yyp=LCA(u,x)p=LCA(u,x)

  • p=xp=x,说明uu在当前链上,直接加进去就行;
  • dep[p]>dep[y]dep[p]>dep[y],说明pp没有被维护到当前链上,那么在虚树上连一条y>xy->x边,把xx弹出,压入p,up,u,就维护好了新的链。
  • dep[p]dep[y]dep[p]\leq dep[y],说明pp在当前链上,仍然连边弹出xx,压入uu

另一种方法是按dfs序排序,加入相邻两点的LCA后再排序,节点的父亲就是节点与前驱的LCA。