树上莫队

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

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)\)的值,就得到了答案
同时,在每次路径转移之前,要先将时间线改到下一个路径的时间线,然后才可以完成移动

posted @ 2019-09-22 20:35  Agakiss  阅读(130)  评论(0编辑  收藏  举报