漂亮的公园 - 牛客
ps:再再再再次感觉自己好菜!此题有个结论:对于一棵树,给定一个点集S,设其最远的两个点为x,y。其它点u到这个点集S的最远距离,必然是到u到x的距离或者是u到y的距离。这样两个集合之间的距离就转化为4个点距离!!!!怎么求每个集合的最远的两个点呢?还是同样的方法,取该集合的两个点作为最远的两个点(直径(不是树的直径)),然后依次加入该集合的其它点,更新即可。集合的直径与如入元素的顺序无关!
const int N = 100005; struct LCA { vector<int> G[N]; int n, d[N], pa[N][20]; void Inite(int cnt) { n = cnt; mem(pa, 0); } void addedge(int u, int v) { G[u].pb(v); G[v].pb(u); } void DFS(int u, int fa, int dep) { d[u] = dep; pa[u][0] = fa; for (auto v : G[u]) if (v != fa) DFS(v, u, dep + 1); } void ST() { DFS(1, 0, 0); for (int i = 1; (1 << i) <= n; ++i) { for (int j = 1; j <= n; ++j) if (pa[j][i - 1]) pa[j][i] = pa[pa[j][i - 1]][i - 1]; } } int getLca(int u, int v) { if (d[u] > d[v]) swap(u, v); rep(i, 0, 20) if ((d[v] - d[u]) & (1 << i)) v = pa[v][i]; if (u == v) return u; for (int i = 19; ~i; --i) if (pa[u][i] != pa[v][i]) { u = pa[u][i]; v = pa[v][i]; } return pa[u][0]; } int computed(int u, int v) { int fa = getLca(u, v); return (d[u] + d[v] - 2 * d[fa]); } }; LCA lca; P od[N]; // 记录每个集合的直径(最远的两个点) int n, q, tot; vector<int> p[N]; map<int, int> c; int main() { sc(n), sc(q); Rep(i, 1, n) { int u; sc(u); if (!c[u]) c[u] = ++tot; p[c[u]].pb(i); } lca.Inite(n); rep(i, 1, n) { int u, v; sc(u), sc(v); lca.addedge(u, v); } lca.ST(); Rep(i, 1, tot) { od[i].first = od[i].second = p[i][0]; int last = 0; rep(j, 1, p[i].size()) { int l = lca.computed(p[i][j], od[i].first); int r = lca.computed(p[i][j], od[i].second); if (l >= r && l > last) { od[i].second = p[i][j]; last = l; } else if (r >= l && r > last) { od[i].first = p[i][j]; last = r; } } } while(q--) { int x, y, res = 0; sc(x), sc(y); if (!c[x] || !c[y]) puts("0"); else if (c[x] == c[y]) { int res = lca.computed(od[c[x]].first, od[c[x]].second); pr(res); } else { int t1 = lca.computed(od[c[x]].first, od[c[y]].first); if (t1 > res) res = t1; int t2 = lca.computed(od[c[x]].first, od[c[y]].second); if (t2 > res) res = t2; int t3 = lca.computed(od[c[x]].second, od[c[y]].first); if (t3 > res) res = t3; int t4 = lca.computed(od[c[x]].second, od[c[y]].second); if (t4 > res) res = t4; pr(res); } } return 0; }