2021.3.22

(mathcal{A})

[HNOI2014]世界树

#include <bits/stdc++.h>
#define fi first
#define se second
using namespace std;
namespace cxcyl {
	const int N = 300300, inf = (int)1e9;
	int n, m, rt, tp, a[N], bo[N], dfn[N], siz[N], dep[N], tn[N], up[N];
	int f[N][21], s[N], ans[N], A[N], timer;
	pair<int, int> g[N];
	vector<int> G[N], E[N];
	inline int read() {
		int x = 0, f = 1; char c = getchar();
		while (c > -1 && c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); }
		if (c == -1) return 0;
		while (c >= '0' && c <= '9') x = x * 10 + c - 48, c = getchar();
		return x * f;
	}
	void dfs0(int u) {
		for (int i = 1; i <= 20; ++i)
			f[u][i] = f[f[u][i - 1]][i - 1];
		dfn[u] = ++timer;
		siz[u] = 1;
		for (int v : G[u])
			if (!dfn[v]) {
				f[v][0] = u;
				dep[v] = dep[u] + 1;
				dfs0(v);
				siz[u] += siz[v];
			}
	}
	void dfs1(int u) {
		g[u] = make_pair(bo[u] ? 0 : inf, u);
		for (int v : E[u]) {
			dfs1(v);
			g[u] = min(g[u], make_pair(g[v].fi + dep[v] - dep[u], g[v].se));
		}
	}
	void dfs2(int u, int D, int x) {
		if (make_pair(D, x) < g[u])
			g[u] = make_pair(D, x);
		else {
			D = g[u].fi;
			x = g[u].se;
		}
		for (int v : E[u])
			dfs2(v, D + dep[v] - dep[u], x);
	}
	void dfs3(int u) {
		tn[u] = g[u].se;
		ans[tn[u]] += siz[u];
		for (int v : E[u]) {
			int x = v;
			for (int i = 20; i >= 0; --i)
				if (dep[f[x][i]] > dep[u])
					x = f[x][i];
			ans[tn[u]] -= siz[up[v] = x];
			dfs3(v);
		}
	}
	void dfs4(int u) {
		for (int v : E[u]) {
			int x = up[v], y = v, H;
			if (tn[u] == tn[v])
				ans[tn[u]] += siz[x] - siz[v];
			else {
				H = dep[tn[v]] + dep[u] - g[u].first;
				H = H & 1 ? H + 1 >> 1 : (tn[v] < tn[u] ? H >> 1 : (H >> 1) + 1);
				for (int i = 20; i >= 0; --i)
					if (dep[f[y][i]] >= H)
						y = f[y][i];
				ans[tn[v]] += siz[y] - siz[v];
				ans[tn[u]] += siz[x] - siz[y];
			}
			dfs4(v);
		}
	}
	void dfs5(int u) {
		up[u] = tn[u] = 0;
		for (int v : E[u]) dfs5(v);
		E[u].clear();
	}
	inline int lca(int u, int v) {
		if (dep[u] < dep[v]) swap(u, v);
		int len = dep[u] - dep[v];
		for (int i = 0; i <= 20; ++i) if (len >> i & 1) u = f[u][i];
		for (int i = 20; i >= 0; --i) if (f[u][i] != f[v][i]) u = f[u][i], v = f[v][i];
		return u == v ? u : f[u][0];
	}
	inline int main() {
		n = read();
		for (int i = 1; i < n; ++i) {
			int u = read(), v = read();
			G[u].push_back(v);
			G[v].push_back(u);
		}
		dfs0(1);
		for (int T = read(); T--; ) {
			//clear
			int m = read();
			for (int i = 1; i <= m; ++i) {
				A[i] = a[i] = read();
				bo[a[i]] = 1;
			}
			sort(a + 1, a + m + 1, [](int x, int y) { return dfn[x] < dfn[y]; });
			s[tp = 1] = a[1];
			for (int i = 2; i <= m; ++i) {
				int l = lca(a[i], s[tp]);
				while (tp > 1 && dep[l] <= dep[s[tp - 1]]) {
					E[s[tp - 1]].push_back(s[tp]);
					--tp;
				}
				if (s[tp] != l) {
					E[l].push_back(s[tp]);
					s[tp] = l;
				}
				s[++tp] = a[i];
			}
			while (tp > 1) {
				E[s[tp - 1]].push_back(s[tp]);
				--tp;
			}
			rt = s[1];
			dfs1(rt);
			dfs2(rt, g[rt].fi, g[rt].se);
			dfs3(rt);
			dfs4(rt);
			ans[tn[rt]] += siz[1] - siz[rt];
			for (int i = 1; i <= m; ++i)
				printf("%d ", ans[A[i]]);
			puts("");
			//clear
			dfs5(rt);
			for (int i = 1; i <= m; ++i)
				bo[a[i]] = ans[a[i]] = 0;
		}
		return 0;
	}
} int main() { return cxcyl::main(); }
原文地址:https://www.cnblogs.com/herald/p/14565303.html