結果
問題 |
No.3194 Do Optimize Your Solution
|
ユーザー |
![]() |
提出日時 | 2025-06-27 22:27:23 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
TLE
|
実行時間 | - |
コード長 | 6,908 bytes |
コンパイル時間 | 3,160 ms |
コンパイル使用メモリ | 231,644 KB |
実行使用メモリ | 86,636 KB |
最終ジャッジ日時 | 2025-06-27 22:27:35 |
合計ジャッジ時間 | 11,566 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 2 |
other | AC * 1 TLE * 1 -- * 15 |
ソースコード
#include <bits/stdc++.h> using namespace std; typedef unsigned long long ll; template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; } template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; } #define vi vector<int> #define vl vector<ll> #define vii vector<pair<int,int>> #define vll vector<pair<ll,ll>> #define vvi vector<vector<int>> #define vvl vector<vector<ll>> #define vvii vector<vector<pair<int,int>>> #define vvll vector<vector<pair<ll,ll>>> #define vst vector<string> #define pii pair<int,int> #define pll pair<ll,ll> #define pb push_back #define all(x) (x).begin(),(x).end() #define mkunique(x) sort(all(x));(x).erase(unique(all(x)),(x).end()) #define fi first #define se second #define mp make_pair #define si(x) int(x.size()) const int mod=998244353,MAX=200005,INF=15<<26; ll ans=0; //auxiliary-tree // https://beet-aizu.github.io/library/tree/auxiliarytree.cpp.html struct LowestCommonAncestor{ int h; vector< vector<int> > G,par; vector<int> dep; LowestCommonAncestor(int n):G(n),dep(n){ h=1; while((1<<h)<=n) h++; par.assign(h,vector<int>(n,-1)); } void add_edge(int u,int v){ G[u].emplace_back(v); G[v].emplace_back(u); } void dfs(int v,int p,int d){ par[0][v]=p; dep[v]=d; for(int u:G[v]) if(u!=p) dfs(u,v,d+1); } void build(int r=0){ int n=G.size(); dfs(r,-1,0); for(int k=0;k+1<h;k++) for(int v=0;v<n;v++) if(~par[k][v]) par[k+1][v]=par[k][par[k][v]]; } int lca(int u,int v){ if(dep[u]>dep[v]) swap(u,v); for(int k=0;k<h;k++) if((dep[v]-dep[u])>>k&1) v=par[k][v]; if(u==v) return u; for(int k=h-1;k>=0;k--) if(par[k][u]!=par[k][v]) u=par[k][u],v=par[k][v]; return par[0][u]; } int distance(int u,int v){ return dep[u]+dep[v]-dep[lca(u,v)]*2; } }; struct AuxiliaryTree : LowestCommonAncestor{ using super = LowestCommonAncestor; vector<int> idx,iru; vl cn,omo,dp; vvll T; AuxiliaryTree(int n):super(n),idx(n),iru(n),cn(n),omo(n),dp(n),T(n){} void dfs(int v,int p,int &pos){ idx[v]=pos++; for(int u:G[v]) if(u!=p) dfs(u,v,pos); } void build(int r=0){ super::build(r); int pos=0; dfs(r,-1,pos); } void add_aux_edge(int u,int v){ T[u].emplace_back(mp(v,distance(u,v))); T[v].emplace_back(mp(u,distance(u,v))); } using super::lca, super::dep; void query(vector<int> &vs){ assert(!vs.empty()); sort(vs.begin(),vs.end(), [&](int a,int b){return idx[a]<idx[b];}); vs.erase(unique(vs.begin(),vs.end()),vs.end()); int k=vs.size(); stack<int> st; st.emplace(vs[0]); for(int i=0;i+1<k;i++){ int w=lca(vs[i],vs[i+1]); if(w!=vs[i]){ int l=st.top();st.pop(); while(!st.empty() and dep[w]<dep[st.top()]){ add_aux_edge(st.top(),l); l=st.top();st.pop(); } if(st.empty() or st.top()!=w){ st.emplace(w); vs.emplace_back(w); } add_aux_edge(w,l); } st.emplace(vs[i+1]); } while(st.size()>1){ int c=st.top();st.pop(); add_aux_edge(st.top(),c); } } void make(int u,int p){ for(auto [to,dd]:T[u]){ if(to==p) continue; make(to,u); dp[u]+=dp[to]; dp[u]+=cn[to]*dd; cn[u]+=cn[to]; } } void solve(int u,int p){ if(iru[u]) cn[u]=1; else cn[u]=0; dp[u]=0; for(auto [to,dd]:T[u]){ dp[u]+=dp[to]; dp[u]+=cn[to]*dd; cn[u]+=cn[to]; } ans+=dp[u]*omo[u]; //cout<<u<<" "<<dp[u]<<" "<<cn[u]<<" "<<omo[u]<<endl; for(auto [to,dd]:T[u]){ if(to==p) continue; ll a=dp[u],b=cn[u],c=dp[to],d=cn[to]; dp[u]-=dp[to]; dp[u]-=cn[to]*dd; cn[u]-=cn[to]; solve(to,u); dp[u]=a; cn[u]=b; dp[to]=c; cn[to]=d; } } void clear(const vector<int> &ws){ for(int w:ws){ cn[w]=0; omo[w]=0; dp[w]=0; iru[w]=0; T[w].clear(); } } }; AuxiliaryTree AT(1); //重心分解(使える版) int N,C=-1; vi G[MAX]; bool centroid[MAX]; int subtree_size[MAX]; int centpar[MAX]; int compute_subtree_size(int u,int p){ int c=1; for(int a:G[u]){ if(a==p||centroid[a]) continue; c+=compute_subtree_size(a,u); } return subtree_size[u]=c; } pair<int,int> search_centroid(int u,int p,int t){ pair<int,int> res={INF,-1}; int s=1,m=0; for(int a:G[u]){ if(a==p||centroid[a]) continue; res=min(res,search_centroid(a,u,t)); m=max(m,subtree_size[a]); s+=subtree_size[a]; } m=max(m,t-s); res=min(res,{m,u}); return res; } void atume(int u,int p,int d,vii &T){ T.pb(mp(d,u)); for(int to:G[u]){ if(to==p||centroid[to]) continue; atume(to,u,d+1,T); } } void calc(vii S,int kei){ if(si(S)<=1) return; vi use; for(auto [a,b]:S) use.pb(b); AT.query(use); for(auto [a,b]:S){ AT.iru[b]=1; AT.omo[b]=a*kei; AT.cn[b]=1; } AT.make(use[0],-1); AT.solve(use[0],-1); AT.clear(use); } void solve_subproblem(int u,int p){ compute_subtree_size(u,-1); int s=search_centroid(u,-1,subtree_size[u]).second; centroid[s]=1; if(C==-1) C=s; centpar[s]=p; vii S={mp(0,s)}; for(int a:G[s]){ if(centroid[a]){ continue; } vii T; atume(a,s,1,T); calc(T,-1); for(auto x:T) S.pb(x); solve_subproblem(a,s); } calc(S,1); centroid[s]=0; } int main(){ std::ifstream in("text.txt"); std::cin.rdbuf(in.rdbuf()); cin.tie(0); ios::sync_with_stdio(false); cin>>N; for(int i=0;i<N-1;i++){ int a,b;cin>>a>>b; a--;b--; G[a].pb(b); G[b].pb(a); } AT=AuxiliaryTree(N); for(int i=0;i<N-1;i++){ int a,b;cin>>a>>b; a--;b--; AT.add_edge(a,b); } AT.build(); solve_subproblem(0,-1); ans*=2; cout<<ans<<endl; }