虚树
虚树做法 虚树是把原树中少量的有效节点和他们两两的LCA拿出来,去除一些无效节点,从而降低复杂度。 如果有效节点是K个的话 加上LCA 虚树中的的点最多为min(n,2*K)个 建虚树的复杂度为O(k*logn) 虚树上树形dp的复杂度为O(k) 证明: 按dfn值从小到大加入有效节点 假设现在加入的节点为X 前面的节点为Y 再前面的节点为Z 如果X与Y的LCA为LCA1 X与Z的LCA为LCA2 LCA1与LCA2里面深度浅的为LCA3 则Y与Z的LCA就为LCA3 是之前存在过的 所以每加入一个点 多出来的LCA只会是一个 建树步骤: 1.dfs得到节点的必要信息 比如dfn deep fa[i][j] minedge[i][j]/maxedge[i][j]. 2.建立一个栈 表示从根要栈顶这条链 每次新加入的节点为X 栈顶为P 则LCA为LCA(X,P) 然后就有两种情况 第一种是X与P不在一条链上 另一种是X与P在一条链上 则dfn(LCA(X,P))<=dfn(P)<dfn(X) 对于第一种情况要仔细讨论 第二种情况直接把X压入栈就行了 第一种情况表示P以下包括P的子树已经没有有效的点了 因为我们是按照dfn的大小来遍历的 void insert( int x){ if (! top){ st[ ++top]= x; return ; } int ll= lca(st