Construction of bzoj3572 _ virtual tree + lca and bzoj3572 construction of lca
World Tree... frozen throne is certainly not a temporary agenda.
I have tried a variety of methods to find things related to the virtual tree. Finally, I understood this question with the help of the big God and DG. Although the gods do not say anything about the virtual tree, I will introduce the application of this question here. (Of course, some great gods do not know what virtual trees are)
For m points of each query, connect them on the original tree to form a subgraph, and add the lca of the m points to the subgraph, if you contract a vertex that is not a query vertex but a vertex whose degree is 2, a virtual tree corresponding to the current query is obtained. (I don't need to care about this name. I just re-constructed a graph)
At this time, we will find that the nodes at both ends of each edge in the virtual tree have their own ownership (this is a nonsense), so we will discuss the attribution of points on this chain, finally, the answer is displayed.
For the process of creating a virtual tree, see the code ...... I also summarized the code at the time. In short, I used the stack to maintain the rightmost link. Every time I updated the elements that were not added and the elements and the stack top, I would just do that.
Ps: it makes sense to see strange variable names.
#include <cstdio>#include <cstring>#include <algorithm>#include <queue>#define N 300000 + 10#define H 20#define INF 1000000000using namespace std;struct node{ int dist, bel; node() { } node(int x, int y) { dist = x; bel = y; }}g[N];struct edge{ int to, next;}e[2*N];int n, m, q, num, top, ind, cont, p[N], flag[N];int fa[N][H], fa_v[N], r[N], d[N], h[N], s[N], st[N];int sum[N], dfn[N], ans[N], val[N], delta[N];inline bool cmp(int x, int y){ return dfn[x] < dfn[y]; }node min(node a, node b){ if (a.dist == b.dist) return a.bel < b.bel ? a : b; return a.dist < b.dist ? a : b;}void read(int &x){ x = 0; char c = getchar(); while(c < '0' || c > '9') c = getchar(); while(c >= '0' && c <= '9') { x = 10*x + c - '0'; c = getchar(); }}void add(int x, int y){ e[++num].to = y; e[num].next = p[x]; p[x] = num;}void init(){ int x, y; read(n); for (int i = 1; i < n; ++i) { read(x), read(y); add(x, y); add(y, x); }}void bfs(){ queue<int>q; q.push(1); fa[1][0] = 1; flag[1] = 1; while(!q.empty()) { int x = q.front(); q.pop(); for (int i = 1; i < H; ++i) fa[x][i] = fa[fa[x][i-1]][i-1]; for (int i = p[x]; i; i = e[i].next) { int k = e[i].to; if (!flag[k]) { d[k] = d[x] + 1; fa[k][0] = x; flag[k] = 1; q.push(k); } } }}void dfs(int x){ sum[x] = 1; dfn[x] = ++ind; for (int i = p[x]; i; i = e[i].next) { int k = e[i].to; if (k != fa[x][0]) { dfs(k); sum[x] += sum[k]; } }}int lca(int x, int y){ if (d[x] > d[y]) swap(x, y); int l = x, r = y; for (int mid = d[r] - d[l], i = 0; mid; ++i, mid >>= 1) if (mid & 1) r = fa[r][i]; if (l == r) return r; for (int i = H - 1; i >= 0; i--) { if (fa[l][i] == fa[r][i]) continue; l = fa[l][i], r = fa[r][i]; } return fa[r][0];}int find(int x, int h){ for (int i = H - 1; i >= 0; i--) if (d[fa[x][i]] >= h) x = fa[x][i]; return x;}void solve(){ top = cont = 0; read(m); for (int i = 1; i <= m; ++i) { read(h[i]); s[++cont] = r[i] = h[i]; g[h[i]] = node(0, h[i]); ans[h[i]] = 0; } sort(h+1, h+m+1, cmp); for (int i = 1; i <= m; ++i) { int x = h[i]; if (!top) { st[++top] = x; fa_v[x] = 0; } else { int anc = lca(x, st[top]); while(d[st[top]] > d[anc]) { if (d[st[top-1]] <= d[anc]) fa_v[st[top]] = anc; top--; } if (st[top] != anc) { s[++cont] = anc; g[anc] = node(INF, 0); fa_v[anc] = st[top]; st[++top] = anc; } fa_v[x] = anc; st[++top] = x; } } sort(s+1, s+cont+1, cmp); for (int i = 1; i <= cont; ++i) { int x = s[i]; val[x] = sum[x]; if (i > 1) delta[x] = d[x] - d[fa_v[x]]; } for (int i = cont; i > 1; i--) { int x = s[i]; g[fa_v[x]] = min(g[fa_v[x]], node(g[x].dist+delta[x], g[x].bel)); } for (int i = 2; i <= cont; ++i) { int x = s[i]; g[x] = min(g[x], node(g[fa_v[x]].dist+delta[x], g[fa_v[x]].bel)); } for (int i = 1; i <= cont; ++i) { int x = s[i], anc = fa_v[x]; if (i == 1) ans[g[x].bel] += n - sum[x]; else { int k = find(x, d[anc]+1); int del = sum[k] - sum[x]; val[anc] -= sum[k]; if (g[anc].bel == g[x].bel) ans[g[x].bel] += del; else { int mid = d[x] - ((g[x].dist+g[fa_v[x]].dist+delta[x])/2-g[x].dist); if ((g[x].dist+g[fa_v[x]].dist+delta[x]) % 2 == 0 && g[x].bel > g[fa_v[x]].bel) ++mid; int tmp = sum[find(x, mid)] - sum[x]; ans[g[x].bel] += tmp; ans[g[fa_v[x]].bel] += del - tmp; } } } for (int i = 1; i <= cont; ++i) ans[g[s[i]].bel] += val[s[i]]; for (int i = 1; i <= m; ++i) printf("%d ", ans[r[i]]); putchar('\n');}void deal(){ bfs(); dfs(1); read(q); while(q--) solve();}int main(){ init(); deal(); return 0;}