#include using namespace std; using ull = unsigned long long; template class SparseTable{ private: T op(T a,T b){return min(a,b);} //条件op(A,A)=A &op(op(A,B),C)=op(A,op(B,C)); T e(T a,T b){return {1001001001,-1};} array check; array,19> table; public: void make(const vector &A){ int n = A.size(); int p2 = 1,l = 0; for(int i=1; i<400000; i++){ if(i == p2) check[i] = l,l++,p2 *= 2; else check[i] = check[i-1]; } for(int i=0; i>1)]); for(int k=n-i+1; k<400000; k++) table[l][k] = {1001001001,-1}; } } T rangeans(int l,int r){//[L,R)だよ. int pos = check[r-l]; r -= 1<> ST; public: array in; void make3(const vector> &Graph,int root){ //直接グラフを渡す. int t = 0,dep = 0,n = Graph.size(),pos = root; vector> depth; vector Itr(n,-1),P(n,-1); while(pos != -1){ depth.push_back({dep,pos}); if(++Itr.at(pos) == 0) in[pos] = t; int to = P.at(pos); if(Itr.at(pos) == Graph.at(pos).size()) out[pos] = ++t; else{ to = Graph.at(pos).at(Itr.at(pos)); if(to == P.at(pos)){ Itr.at(pos)++; if(Itr.at(pos) == Graph.at(pos).size()) out[pos] = ++t; else to = Graph.at(pos).at(Itr.at(pos)); } } if(to != P.at(pos)) dist[to] = dist[pos]+1,P.at(to) = pos,t++,dep++; else dep--; pos = to; } ST.make(depth); } int lca(int u,int v){ int tu = in[u],tv = in[v]; if(tu > tv) swap(tu,tv); return ST.rangeans(tu,tv+1).second; } }; LCA L; bool stop[200000]; int in[200000],start[200001],To[400000]; vector> in2; pair>,vector>>> AuxiliaryTree(const vector &A,int maxa){ //色ごとに木を構築するやつ O(NlogN) 定数悪い実装. //return {色ごとの実際の頂点番号,色ごとのTree} //重み付きだったら修正必須. int N = A.size(); vector> ret1(maxa); vector>> ret2(maxa); for(auto [t,i] : in2) if(A.at(i) != -1) ret1.at(A.at(i)).emplace_back(i); for(int i=0; i> st; for(int k=0; k V[200000]; int main(){ ios_base::sync_with_stdio(false); cin.tie(nullptr); int N; cin >> N; //if(N != 199910) return 0; vector> Graph(N); for(int i=0; i> u >> v,u--; v--; Graph.at(u).emplace_back(v); Graph.at(v).emplace_back(u); } { int point = 0; for(int i=0; i> u >> v,u--; v--; Graph.at(u).emplace_back(v); Graph.at(v).emplace_back(u); } L.make3(Graph,0); for(int i=0; i int { stack> st; st.push({1,s,start[s],-1}); int bring = 0; while(st.size()){ auto &[vs,pos,i,back] = st.top(); vs += bring; bring = 0; while(true){ if(i == start[pos+1]){bring = vs; st.pop(); break;} int to = To[i]; i++; if(stop[to] || to == back) continue; st.push({1,to,start[to],pos}); break; } } return bring; }; auto centroid = [&](int s,int siz) -> int { stack> st; st.push({1,s,start[s],-1,true}); int bring = 0; while(st.size()){ auto &[vs,pos,i,back,ok] = st.top(); if(bring > siz/2) ok = false; vs += bring; bring = 0; while(true){ if(i == start[pos+1]){ bring = vs; if(siz-bring <= siz/2 && ok) return pos; st.pop(); break; } int to = To[i]; i++; if(stop[to] || to == back) continue; st.push({1,to,start[to],pos,true}); break; } } return -1; }; vector Ps = {0}; vector T(10); while(Ps.size()){ T.at(2) -= clock(); for(auto &p : Ps){ int siz = findsiz(p); if(siz != 1) p = centroid(p,siz); else stop[p] = true,p = -1; } T.at(2) += clock(); vector C1(N,-1),C2(N,-1); int cpos1 = 0,cpos2 = 0; for(auto &p : Ps){ if(p == -1) continue; auto dfs = [&](int s,int b) -> void { stack> st; st.push({s,start[s],b}); C1.at(s) = cpos1,C2.at(s) = cpos2; while(st.size()){ auto &[pos,i,back] = st.top(); while(true){ if(i == start[pos+1]){st.pop(); break;} int to = To[i]; i++; if(stop[to] || to == back) continue; C1.at(to) = cpos1,C2.at(to) = cpos2; st.push({to,start[to],pos}); break; } } }; for(int i=start[p]; i void { stack> st; st.push({s,start[s],-1}); V[s] = {1,0,dist[s],0}; int dep = 0; while(st.size()){ auto &[pos,i,back] = st.top(); while(true){ if(i == start[pos+1]){dep--,st.pop(); break;} int to = To[i++]; if(stop[to] || to == back) continue; dep++; V[to] = {1,dep,dist[to],dep*dist[to]}; st.push({to,start[to],pos}); break; } } }; dfs(root); } { auto dfs = [&](auto dfs,int pos,int back) -> tuple { int p = B.at(pos); auto [c,d,e,s] = V[p]; V[p] = {0,0,0,0}; ull di = dist[p]*2; for(auto to : G.at(pos)){ if(to == back) continue; auto [c2,d2,e2,s2] = dfs(dfs,to,pos); if(c2 == 0) continue; answer -= di*d*c2; answer -= di*d2*c; answer += d*e2+e*d2; answer += s*c2+s2*c; c += c2,d += d2,e += e2,s += s2; } return {c,d,e,s}; }; dfs(dfs,0,-1); } cpos1++; } cpos2 = 0; for(auto p : Ps) if(p != -1) for(int i=start[p]; i void { stack> st; st.push({s,start[s],b}); V[s] = {1,1,dist[s],dist[s]}; int dep = 1; while(st.size()){ auto &[pos,i,back] = st.top(); while(true){ if(i == start[pos+1]){dep--,st.pop(); break;} int to = To[i]; i++; if(stop[to] || to == back) continue; dep++; V[to] = {1,dep,dist[to],dep*dist[to]}; st.push({to,start[to],pos}); break; } } }; dfs(root,p); } { auto dfs = [&](auto dfs,int pos,int back) -> tuple { int p = B.at(pos); auto [c,d,e,s] = V[p]; V[p] = {0,0,0,0}; ull di = dist[p]*2; for(auto to : G.at(pos)){ if(to == back) continue; auto [c2,d2,e2,s2] = dfs(dfs,to,pos); answer += di*(d*c2+d2*c); answer -= d*e2+e*d2; answer -= s*c2+s2*c; c += c2,d += d2,e += e2,s += s2; } return {c,d,e,s}; }; dfs(dfs,0,-1); } cpos2++; } T.at(1) += clock(); vector next; for(auto &p : Ps){ if(p == -1) continue; for(int i=start[p]; i