結果
問題 | No.3193 Submit Your Solution |
ユーザー |
|
提出日時 | 2025-06-28 12:44:52 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
RE
|
実行時間 | - |
コード長 | 12,265 bytes |
コンパイル時間 | 3,912 ms |
コンパイル使用メモリ | 262,084 KB |
実行使用メモリ | 168,556 KB |
最終ジャッジ日時 | 2025-06-28 12:45:11 |
合計ジャッジ時間 | 18,846 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 2 |
other | RE * 1 TLE * 1 -- * 15 |
ソースコード
#include <bits/stdc++.h> using namespace std; using ull = unsigned long long; template <typename T> 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<int,400000> check; array<array<T,400000>,19> table; public: void make(const vector<T> &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<n; i++) table[0][i] = A[i]; for(int i=n; i<400000; i++) table[0][i] = {1001001001,-1}; l = 1; for(int i=2; i<=n; i*=2,l++){ for(int k=0; k<=n-i; k++) table[l][k] = op(table[l-1][k],table[l-1][k+(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<<pos; return op(table[pos][l],table[pos][r]); } }; class LCA{ private: SparseTable<pair<int,int>> ST; public: vector<int> in,out; vector<ull> dist; void make1(const vector<int> &P){// p0=-1でp1以降だけ int r = 0; vector<vector<int>> G(P.size()+1); for(int i=0; i<P.size(); i++) G.at(P.at(i)).push_back(i+1); make3(G,r); } void make2(const vector<int> &P){//pi=-1 iは固定されていない. int r = -1; vector<vector<int>> G(P.size()); for(int i=0; i<P.size(); i++){ if(P.at(i) == -1) r = i; else G.at(P.at(i)).push_back(i); } make3(G,r); } void make3(const vector<vector<int>> &Graph,int root){ //直接グラフを渡す. int t = 0,dep = 0,n = Graph.size(),pos = root; dist.resize(n),in.resize(n),out.resize(n); vector<pair<int,int>> depth; vector<int> Itr(n,-1),P(n,-1); while(pos != -1){ depth.push_back({dep,pos}); if(++Itr.at(pos) == 0) in.at(pos) = t; int to = P.at(pos); if(Itr.at(pos) == Graph.at(pos).size()) out.at(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.at(pos) = ++t; else to = Graph.at(pos).at(Itr.at(pos)); } } if(to != P.at(pos)) dist.at(to) = dist.at(pos)+1,P.at(to) = pos,t++,dep++; else dep--; pos = to; } ST.make(depth); } int lca(int u,int v){ int tu = in.at(u),tv = in.at(v); if(tu > tv) swap(tu,tv); return ST.rangeans(tu,tv+1).second; } int twodist(int u,int v){return dist.at(u)+dist.at(v)-2*dist.at(lca(u,v));} int onedist(int u){return dist.at(u);} pair<vector<int>,vector<int>> getinout(){return {in,out};} }; LCA L; int in[200000],out[200000]; vector<pair<int,int>> in2; pair<vector<vector<int>>,vector<vector<vector<int>>>> AuxiliaryTree(const vector<int> &A,int maxa){ //色ごとに木を構築するやつ O(NlogN) 定数悪い実装. //return {色ごとの実際の頂点番号,色ごとのTree} //重み付きだったら修正必須. int N = A.size(); vector<vector<int>> ret1(maxa); for(auto [t,i] : in2) if(A.at(i) != -1) ret1.at(A.at(i)).emplace_back(i); for(auto &as : ret1){ int n = as.size(); for(int i=0; i<n-1; i++){ int pos1 = as.at(i),pos2 = as.at(i+1); int pos3 = L.lca(pos1,pos2); assert(pos3 != -1); as.emplace_back(pos3); } sort(as.begin(),as.end(),[&](auto &a,auto &b){return in[a]<in[b];}); as.erase(unique(as.begin(),as.end()),as.end()); } vector<vector<vector<int>>> ret2(maxa); for(int i=0; i<maxa; i++){ int siz = ret1.at(i).size(); ret2.at(i).resize(siz); stack<pair<int,int>> st; for(int k=0; k<siz; k++){ int pos = ret1.at(i).at(k),out1 = out[pos]; while(st.size()){ auto[bk,out2] = st.top(); if(out1 < out2){ ret2.at(i).at(bk).emplace_back(k); ret2.at(i).at(k).emplace_back(bk); break; } else st.pop(); } st.push({k,out1}); } } return{ret1,ret2}; } tuple<ull,ull,ull,ull> V[200000]; ull dist2[200000]; int main(){ ios_base::sync_with_stdio(false); cin.tie(nullptr); int N; cin >> N; //if(N != 199910) return 0; vector<vector<int>> Graph(N); for(int i=0; i<N-1; i++){ int u = i,v = i+1; cin >> u >> v,u--; v--; Graph.at(u).push_back(v); Graph.at(v).push_back(u); } vector<int> To((N-1)*2),start(N+1); { int point = 0; for(int i=0; i<N; i++){ start.at(i) = point; for(auto to : Graph.at(i)) To.at(point++) = to; Graph.at(i).clear(); } start.back() = point; } for(int i=0; i<N-1; i++){ int u = i,v = i+1; cin >> u >> v,u--; v--; Graph.at(u).push_back(v); Graph.at(v).push_back(u); } L.make3(Graph,0); for(int i=0; i<N; i++) in[i] = L.in.at(i),out[i] = L.out.at(i),dist2[i] = L.dist.at(i); in2.resize(N); for(int i=0; i<N; i++) in2.at(i) = {in[i],i}; sort(in2.begin(),in2.end()); ull answer = 0; vector<bool> stop(N); auto findsiz = [&](int s) -> int { stack<tuple<int,int,int,int>> st; st.push({1,s,start.at(s),-1}); int bring = 0; while(st.size()){ auto &[vs,pos,i,back] = st.top(); vs += bring; bring = 0; while(true){ if(i == start.at(pos+1)){bring = vs; st.pop(); break;} int to = To.at(i); i++; if(stop.at(to) || to == back) continue; st.push({1,to,start.at(to),pos}); break; } } return bring; }; auto centroid = [&](int s,int siz) -> int { stack<tuple<int,int,int,int,bool>> st; st.push({1,s,start.at(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.at(pos+1)){ bring = vs; if(siz-bring <= N/2 && ok) return pos; st.pop(); break; } int to = To.at(i); i++; if(stop.at(to) || to == back) continue; st.push({1,to,start.at(to),pos,true}); break; } } return -1; }; vector<int> Ps = {0}; while(Ps.size()){ for(auto &p : Ps){ int siz = findsiz(p); if(siz != 1) p = centroid(p,siz); else stop.at(p) = true,p = -1; } vector<int> 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<tuple<int,int,int>> st; st.push({s,start.at(s),b}); C1.at(s) = cpos1,C2.at(s) = cpos2; while(st.size()){ auto &[pos,i,back] = st.top(); while(true){ if(i == start.at(pos+1)){st.pop(); break;} int to = To.at(i); i++; if(stop.at(to) || to == back) continue; C1.at(to) = cpos1,C2.at(to) = cpos2; st.push({to,start.at(to),pos}); break; } } }; for(int i=start.at(p); i<start.at(p+1); i++){ int to = To.at(i); if(stop.at(to) == false) dfs(to,p),cpos2++; } C1.at(p) = cpos1++; } auto[B1,G1] = AuxiliaryTree(C1,cpos1); auto[B2,G2] = AuxiliaryTree(C2,cpos2); int idx = 0; for(auto &G : G1){ int root = -1; while(root == -1) root = Ps.at(idx++); idx--; { auto dfs = [&](int s) -> void { stack<tuple<int,int,int>> st; st.push({s,start.at(s),-1}); V[s] = {1,0,dist2[s],0}; int dep = 0; while(st.size()){ auto &[pos,i,back] = st.top(); while(true){ if(i == start.at(pos+1)){dep--,st.pop(); break;} int to = To.at(i); i++; if(stop.at(to) || to == back) continue; dep++; V[to] = {1,dep,dist2[to],dep*dist2[to]}; st.push({to,start.at(to),pos}); break; } } }; dfs(root); } { auto dfs = [&](auto dfs,int pos,int back) -> tuple<ull,ull,ull,ull> { int p = B1.at(idx).at(pos); auto [c,d,e,s] = V[p]; V[p] = {0,0,0,0}; ull di = dist2[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+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); } idx++; } cpos2 = 0; for(auto p : Ps) if(p != -1) for(int i=start.at(p); i<start.at(p+1); i++){ int root = To.at(i); if(stop.at(root)) continue; auto &G = G2.at(cpos2); auto &B = B2.at(cpos2); { auto dfs = [&](int s,int b) -> void { stack<tuple<int,int,int>> st; st.push({s,start.at(s),b}); V[s] = {1,1,dist2[s],dist2[s]}; int dep = 1; while(st.size()){ auto &[pos,i,back] = st.top(); while(true){ if(i == start.at(pos+1)){dep--,st.pop(); break;} int to = To.at(i); i++; if(stop.at(to) || to == back) continue; dep++; V[to] = {1,dep,dist2[to],dep*dist2[to]}; st.push({to,start.at(to),pos}); break; } } }; dfs(root,p); } { auto dfs = [&](auto dfs,int pos,int back) -> tuple<ull,ull,ull,ull> { int p = B.at(pos); auto [c,d,e,s] = V[p]; V[p] = {0,0,0,0}; ull di = dist2[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++; } vector<int> next; for(auto &p : Ps){ if(p == -1) continue; for(int i=start.at(p); i<start.at(p+1); i++){ int to = To.at(i); if(!stop.at(to)) next.emplace_back(to); } stop.at(p) = true; } swap(Ps,next); } answer *= 2; //answer = 77714187941852070; //さいあく cout << answer << endl; }