【题目链接】
【双倍经验链接】
【思路要点】
- 用长链剖分维护DP数组。
- 时间复杂度\(O(N)\)。
【代码】
#include<bits/stdc++.h> using namespace std; const int MAXN = 1e5 + 5; const int MAXP = 1e6 + 5; template <typename T> void chkmax(T &x, T y) {x = max(x, y); } template <typename T> void chkmin(T &x, T y) {x = min(x, y); } template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> void writeln(T x) { write(x); puts(""); } struct Node {int nxt; long long val; } p[MAXP]; int n, depth[MAXN], son[MAXN], Max[MAXN]; int tot, headf[MAXN], headg[MAXN]; vector <int> a[MAXN]; long long ans; void dfs(int pos, int fa) { Max[pos] = depth[pos] = depth[fa] + 1; for (unsigned i = 0; i < a[pos].size(); i++) if (a[pos][i] != fa) { dfs(a[pos][i], pos); chkmax(Max[pos], Max[a[pos][i]]); if (son[pos] == 0 || Max[a[pos][i]] > Max[son[pos]]) son[pos] = a[pos][i]; } } void work(int pos, int fa) { for (unsigned i = 0; i < a[pos].size(); i++) if (a[pos][i] != fa) work(a[pos][i], pos); headf[pos] = ++tot; p[tot] = (Node) {headf[son[pos]], 1}; headg[pos] = p[headg[son[pos]]].nxt; if (headg[pos] == 0) headg[pos] = ++tot; for (unsigned i = 0; i < a[pos].size(); i++) { int tmp = a[pos][i]; if (tmp != fa && tmp != son[pos]) { int posf = headf[tmp], nowf = p[headf[pos]].nxt; if (p[headg[tmp]].nxt == 0) p[headg[tmp]].nxt = ++tot; int posg = p[headg[tmp]].nxt, nowg = headg[pos]; for (int j = depth[tmp]; j <= Max[tmp]; j++) { p[nowg].val += p[posg].val; if (p[nowg].nxt == 0) p[nowg].nxt = ++tot; nowg = p[nowg].nxt; ans += p[nowg].val * p[posf].val; p[nowg].val += p[nowf].val * p[posf].val; if (p[posg].nxt == 0) p[posg].nxt = ++tot; posg = p[posg].nxt; ans += p[nowf].val * p[posg].val; p[nowf].val += p[posf].val; nowf = p[nowf].nxt; posf = p[posf].nxt; } } } ans += p[headg[pos]].val; } int main() { read(n); for (int i = 1; i <= n - 1; i++) { int x, y; read(x), read(y); a[x].push_back(y); a[y].push_back(x); } dfs(1, 0); work(1, 0); writeln(ans); return 0; }