回想Day1真是可怕,场场都是倒数的。。。。(金牌爷太强了)
题目如下(吉老师出的题)
传送门:https://ac.nowcoder.com/acm/contest/3979/E
个人感觉这题不是很难那种(不过比赛时候确实没写出来)因为确实没有练习过树上差分,不知道树上前缀和有什么用。。。
公式就是这样了,吉老师写的更简便,(但是看不懂)
#include<iostream> #include<cstring> #include<algorithm> #include<vector> using namespace std; typedef long long ll; const int maxn = 3e5 + 100; ll dep[maxn]; int f[maxn][30]; ll dp[maxn];//答案 ll list[maxn];//前缀 ll cnt[maxn]; ll ans[maxn]; vector<int>G[maxn]; void insert(int be, int en) { G[be].push_back(en); } int dfs(int x, int fa) { dep[x] = dep[fa] + 1; for (int i = 0; i < G[x].size(); i++) { int p = G[x][i]; if (p == fa) continue; f[p][0] = x; dfs(p, x); } return 0; } int LCA(int x, int y) { if (dep[x] > dep[y]) swap(x, y); for (int i = 22; i >= 0; i--) { if (dep[x] <= dep[f[y][i]]) { y = f[y][i]; } } if (x == y) return x; for (int i = 22; i >= 0; i--) { if (f[x][i] != f[y][i]) { x = f[x][i]; y = f[y][i]; } } return f[x][0]; } struct node { int be, en; ll len; }que[maxn]; int dfs1(int x, int fa) { for (int i = 0; i < G[x].size(); i++) { int p = G[x][i]; if (p == fa) continue; dfs1(p, x); ans[x] += ans[p]; cnt[x] += cnt[p]; } list[x] = cnt[x]; return 0; } int dfs2(int x, int fa) { for (int i = 0; i < G[x].size(); i++) { int p = G[x][i]; if (p == fa) continue; dfs2(p, x); ans[x] += ans[p]; list[x] += list[p]; } return 0; } int dfs3(int x, int fa) { for (int i = 0; i < G[x].size(); i++) { int p = G[x][i]; if (p == fa) continue; dp[p] = dp[x] + 2 * list[p] - ans[p] - cnt[p]; dfs3(p, x); } return 0; } int main() { int n, m; int be, en; scanf("%d %d", &n, &m); for (int i = 1; i < n; i++) { scanf("%d %d", &be, &en); insert(be, en); insert(en, be); } dfs(1, 0); for (int k = 1; k < 25; k++) { for (int i = 1; i <= n; i++) { f[i][k] = f[f[i][k - 1]][k - 1]; } } ll cns = 0; for (int i = 0; i < m; i++) { scanf("%d %d", &be, &en); int root = LCA(be, en); cnt[be]++; cnt[en]++; cnt[root] -= 2; ll d = dep[be] + dep[en] - 2 * dep[root]; que[i].be = be; que[i].en = en; que[i].len = d; dp[1] += 1LL*(dep[be] - dep[root])*(dep[en] - dep[root]); } dfs1(1, -1); ll len; for (int i = 0; i < m; i++) { be = que[i].be; en = que[i].en; len = que[i].len; int root = LCA(be, en); ans[be] += len; ans[en] += len; ans[root] -= 2 * len; list[root] -= (dep[be] - dep[root]); list[root] -= (dep[en] - dep[root]); } dfs2(1, -1); dfs3(1, -1); for (int i = 1; i <= n; i++) { printf("%lld ", dp[i]); } return 0; }