树上莫队

建议有莫队和待修莫队的基础的人观看
首先,我们要先确定怎么把树分块

void dfs(int u, int fa) {
	int t = top;
	for (register int i = head[u]; i; i = t[i].nxt) {
		int v = t[i].ver;
		if (v != fa)
			deep[v] = deep[u] + 1, dfs(v, u);
		if (top - t >= B) {
			++tot;
			while (top > t)
				bl[stack[top--]] = tot;
		}
	}
	stack[++top] = u;
}
...
while (top)
	bl[stack[top--]] = tot;

以上方法可以稳定的将树分块的大小稳定在([B,3B])之间
排序方法是:先按(bl[opt.u])再按(bl[opt.v])再按(opt.tim)
然后我们考虑指针移动,
假设我们做完了路径(u1→v1)
现在我们要做路径(u2→v2)
我们用一个(vis)数组来记录每个点有没有被访问过
我们将(u1→lca(u1,v1)→v1)(不包括(lca(u1,v1)))的每个点取反,同时将取值也将其去反
再将(u2→lca(u2,v2)→v2)(不包括(lca(u2,v2)))的每个点取反,同时将取值也取反
在统计答案的时候再加上(lca(u2,v2))的值,就得到了答案
同时,在每次路径转移之前,要先将时间线改到下一个路径的时间线,然后才可以完成移动

只要有想见的人,就不是孤身一人了。
原文地址:https://www.cnblogs.com/Agakiss/p/11569066.html