using i64 = int64_t; using pii = std::pair<int, int>;
constint kMaxN = 2e5 + 5;
int n; i64 ans = 0; int p[kMaxN], dep[kMaxN], sz[kMaxN], wson[kMaxN], st[kMaxN][20]; int dfn[kMaxN], idx[kMaxN], top[kMaxN]; std::vector<int> G[kMaxN];
/* sum1[i] (bit1) : i 或者 i 的轻子树的标记点到 i 的距离和 cnt1[i] (bit2) : i 或者 i 的轻子树的标记点个数 sum2[i] (bit3) : i 或者 i 的轻子树的标记点个数 * dep[i] cnt2[i] (bit4) : i 的子树内的标记点个数 sum3[i] (bit5) : i 的子树内标记点的 dep 和 */
structBIT { i64 c[kMaxN]; voidupd(int x, int v){ for (; x <= 2 * n; x += x & -x) c[x] += v; } voidupd(int l, int r, int v){ if (l <= r) upd(l, v), upd(r + 1, -v); } i64 qry(int x){ i64 ret = 0; for (; x; x -= x & -x) ret += c[x]; return ret; } i64 qry(int l, int r){ return l <= r ? qry(r) - qry(l - 1) : 0; } } bit1, bit2, bit3, bit4, bit5;
intget(int x, int y){ return dfn[x] < dfn[y] ? x : y; }
voiddfs1(int u, int fa){ sz[u] = 1, dep[u] = dep[fa] + 1, p[u] = fa; for (auto v : G[u]) { if (v == fa) continue; dfs1(v, u); sz[u] += sz[v]; if (sz[v] > sz[wson[u]]) wson[u] = v; } }
voiddfs2(int u, int fa, int t){ staticint cnt = 0; st[dfn[u] = ++cnt][0] = fa, idx[cnt] = u, top[u] = t; if (wson[u]) dfs2(wson[u], u, t); for (auto v : G[u]) { if (v == fa || v == wson[u]) continue; dfs2(v, u, v); } }
intLCA(int x, int y){ if (x == y) return x; if (dfn[x] > dfn[y]) std::swap(x, y); int k = std::__lg(dfn[y] - dfn[x]); returnget(st[dfn[x] + 1][k], st[dfn[y] - (1 << k) + 1][k]); }
intgetfa(int x, int k){ assert(dep[x] - 1 >= k); for (; x; k -= dep[x] - dep[p[top[x]]], x = p[top[x]]) { if (k <= dep[x] - dep[top[x]]) return idx[dfn[x] - k]; } assert(0); }
intmove(int x, int y, int k){ int lca = LCA(x, y), len = dep[x] + dep[y] - 2 * dep[lca]; assert(k <= len); if (k <= dep[x] - dep[lca]) returngetfa(x, k); elsereturngetfa(y, len - k); }
pii merge(pii a, pii b){ if (a.second < b.second) std::swap(a, b); auto [u1, r1] = a; auto [u2, r2] = b; int dis = getdis(u1, u2); if (dis <= r1 - r2) return a; assert((r1 + r2 + dis) % 2 == 0); int r = (r1 + r2 + dis) / 2, u = move(u1, u2, r - r1); return {u, r}; }
voidprework(){ dfs1(1, 0), dfs2(1, 0, 1); for (int i = 1; i <= std::__lg(2 * n - 1); ++i) for (int j = 1; j <= 2 * n - 1 - (1 << i) + 1; ++j) st[j][i] = get(st[j][i - 1], st[j + (1 << (i - 1))][i - 1]); }
voidupdate(int x, int v){ bit4.upd(dfn[x], v), bit5.upd(dfn[x], v * dep[x]); for (int i = x; i; i = p[top[i]]) { bit1.upd(dfn[i], v * (dep[x] - dep[i])), bit2.upd(dfn[i], v); bit3.upd(dfn[i], v * dep[i]); } }
i64 query(int x){ i64 ret = 0; int lst = 0; for (int i = x; i; i = p[top[i]]) { int cnt = bit2.qry(dfn[top[i]], dfn[i] - 1); ret += 1ll * cnt * dep[x] - bit3.qry(dfn[top[i]], dfn[i] - 1) + bit1.qry(dfn[top[i]], dfn[i] - 1); int cnt1 = bit4.qry(dfn[i], dfn[i] + sz[i] - 1); ret += 1ll * cnt1 * (dep[x] - dep[i]) + bit5.qry(dfn[i], dfn[i] + sz[i] - 1) - 1ll * cnt1 * dep[i]; if (lst) { int cnt2 = bit4.qry(dfn[lst], dfn[lst] + sz[lst] - 1); ret -= 1ll * cnt2 * (dep[x] - dep[i]) + bit5.qry(dfn[lst], dfn[lst] + sz[lst] - 1) - 1ll * cnt2 * dep[i]; } lst = top[i]; } return ret; }
voidsolve(int l, int r){ static pii c[kMaxN]; staticint t1[kMaxN], t2[kMaxN]; static i64 sum[kMaxN]; if (l == r) return; int mid = (l + r) >> 1; solve(l, mid), solve(mid + 1, r); c[mid] = {mid, 0}, c[mid + 1] = {mid + 1, 0}; for (int i = mid - 1; i >= l; --i) c[i] = merge(c[i + 1], {i, 0}); for (int i = mid + 2; i <= r; ++i) c[i] = merge(c[i - 1], {i, 0}); for (int i = mid + 1; i <= r; ++i) sum[i] = sum[i - 1] + c[i].second; int nl = mid + 1, nr = mid; for (int i = l; i <= mid; ++i) { int L = mid, R = r + 1; t1[i] = mid, t2[i] = r + 1; while (L + 1 < R) { int mid = (L + R) >> 1; if (merge(c[i], c[mid]) == c[i]) L = t1[i] = mid; else R = mid; } L = t1[i], R = r + 1; while (L + 1 < R) { int mid = (L + R) >> 1; if (merge(c[i], c[mid]) == c[mid]) R = t2[i] = mid; else L = mid; } ans += 2ll * c[i].second * (t1[i] - mid) + 2ll * (sum[r] - sum[t2[i] - 1]); ans += 1ll * c[i].second * (t2[i] - t1[i] - 1) + sum[t2[i] - 1] - sum[t1[i]]; for (; nr < t2[i] - 1; update(c[++nr].first, 1)) {} for (; nl > t1[i] + 1; update(c[--nl].first, 1)) {} for (; nr > t2[i] - 1; update(c[nr--].first, -1)) {} for (; nl < t1[i] + 1; update(c[nl++].first, -1)) {} ans += query(c[i].first); } for (int i = nl; i <= nr; ++i) update(c[i].first, -1); }
voiddickdreamer(){ std::cin >> n; for (int i = 1; i < n; ++i) { int u, v; std::cin >> u >> v; G[u].emplace_back(i + n), G[i + n].emplace_back(u); G[v].emplace_back(i + n), G[i + n].emplace_back(v); } prework(), solve(1, n); std::cout << ans / 2 << '\n'; }