結果
問題 |
No.3194 Do Optimize Your Solution
|
ユーザー |
![]() |
提出日時 | 2025-06-27 23:33:17 |
言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
結果 |
TLE
|
実行時間 | - |
コード長 | 21,029 bytes |
コンパイル時間 | 5,964 ms |
コンパイル使用メモリ | 333,412 KB |
実行使用メモリ | 118,080 KB |
最終ジャッジ日時 | 2025-06-27 23:33:33 |
合計ジャッジ時間 | 14,860 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge1 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 2 |
other | TLE * 2 -- * 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; // 提出日時からエスパー(は?) // https://judge.yosupo.jp/submission/294286 #line 1 "c.cpp" #pragma GCC optimize("Ofast,unroll-loops") #pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt") #line 2 "/Users/noya2/Desktop/Noya2_library/template/template.hpp" using namespace std; #include<bits/stdc++.h> #line 1 "/Users/noya2/Desktop/Noya2_library/template/inout_old.hpp" namespace noya2 { template <typename T, typename U> ostream &operator<<(ostream &os, const pair<T, U> &p){ os << p.first << " " << p.second; return os; } template <typename T, typename U> istream &operator>>(istream &is, pair<T, U> &p){ is >> p.first >> p.second; return is; } template <typename T> ostream &operator<<(ostream &os, const vector<T> &v){ int s = (int)v.size(); for (int i = 0; i < s; i++) os << (i ? " " : "") << v[i]; return os; } template <typename T> istream &operator>>(istream &is, vector<T> &v){ for (auto &x : v) is >> x; return is; } void in() {} template <typename T, class... U> void in(T &t, U &...u){ cin >> t; in(u...); } void out() { cout << "\n"; } template <typename T, class... U, char sep = ' '> void out(const T &t, const U &...u){ cout << t; if (sizeof...(u)) cout << sep; out(u...); } template<typename T> void out(const vector<vector<T>> &vv){ int s = (int)vv.size(); for (int i = 0; i < s; i++) out(vv[i]); } struct IoSetup { IoSetup(){ cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(15); cerr << fixed << setprecision(7); } } iosetup_noya2; } // namespace noya2 #line 1 "/Users/noya2/Desktop/Noya2_library/template/const.hpp" namespace noya2{ const int iinf = 1'000'000'007; const long long linf = 2'000'000'000'000'000'000LL; const long long mod998 = 998244353; const long long mod107 = 1000000007; const long double pi = 3.14159265358979323; const vector<int> dx = {0,1,0,-1,1,1,-1,-1}; const vector<int> dy = {1,0,-1,0,1,-1,-1,1}; const string ALP = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const string alp = "abcdefghijklmnopqrstuvwxyz"; const string NUM = "0123456789"; void yes(){ cout << "Yes\n"; } void no(){ cout << "No\n"; } void YES(){ cout << "YES\n"; } void NO(){ cout << "NO\n"; } void yn(bool t){ t ? yes() : no(); } void YN(bool t){ t ? YES() : NO(); } } // namespace noya2 #line 2 "/Users/noya2/Desktop/Noya2_library/template/utils.hpp" #line 6 "/Users/noya2/Desktop/Noya2_library/template/utils.hpp" namespace noya2{ unsigned long long inner_binary_gcd(unsigned long long a, unsigned long long b){ if (a == 0 || b == 0) return a + b; int n = __builtin_ctzll(a); a >>= n; int m = __builtin_ctzll(b); b >>= m; while (a != b) { int mm = __builtin_ctzll(a - b); bool f = a > b; unsigned long long c = f ? a : b; b = f ? b : a; a = (c - b) >> mm; } return a << std::min(n, m); } template<typename T> T gcd_fast(T a, T b){ return static_cast<T>(inner_binary_gcd(std::abs(a),std::abs(b))); } long long sqrt_fast(long long n) { if (n <= 0) return 0; long long x = sqrt(n); while ((x + 1) * (x + 1) <= n) x++; while (x * x > n) x--; return x; } template<typename T> T floor_div(const T n, const T d) { assert(d != 0); return n / d - static_cast<T>((n ^ d) < 0 && n % d != 0); } template<typename T> T ceil_div(const T n, const T d) { assert(d != 0); return n / d + static_cast<T>((n ^ d) >= 0 && n % d != 0); } template<typename T> void uniq(std::vector<T> &v){ std::sort(v.begin(),v.end()); v.erase(unique(v.begin(),v.end()),v.end()); } template <typename T, typename U> inline bool chmin(T &x, U y) { return (y < x) ? (x = y, true) : false; } template <typename T, typename U> inline bool chmax(T &x, U y) { return (x < y) ? (x = y, true) : false; } template<typename T> inline bool range(T l, T x, T r){ return l <= x && x < r; } } // namespace noya2 #line 8 "/Users/noya2/Desktop/Noya2_library/template/template.hpp" #define rep(i,n) for (int i = 0; i < (int)(n); i++) #define repp(i,m,n) for (int i = (m); i < (int)(n); i++) #define reb(i,n) for (int i = (int)(n-1); i >= 0; i--) using ld = long double; using uint = unsigned int; using ull = unsigned long long; using pil = pair<int,ll>; using pli = pair<ll,int>; namespace noya2{ /* ~ (. _________ . /) */ } using namespace noya2; #line 3 "c.cpp" struct fast_lca { int n; std::vector<int> down; std::vector<int> a, pre, suf; std::vector<std::vector<int>> st; static constexpr int LG = 4; static constexpr int MASK = (1 << LG) - 1; fast_lca (const std::vector<int> &par) : n(par.size()), down(n), a(n) { //ncout<<n<<endl; assert(n >= 1); // subtree size - 1 for (int i = n - 1; i >= 1; i--){ down[par[i]] += down[i] + 1; } // euler tour time for (int i = 1; i < n; i++){ down[i] = std::exchange(down[par[i]], down[par[i]] - down[i] - 1); } // build a, pre, suf for (int i = 1; i < n; i++){ a[down[i] - 1] = par[i]; } pre = suf = a; for (int i = 1; i < n; i++){ if (i & MASK){ if (pre[i] > pre[i - 1]){ pre[i] = pre[i - 1]; } } } for (int i = n - 1; i >= 1; i--){ if (i & MASK){ if (suf[i - 1] > suf[i]){ suf[i - 1] = suf[i]; } } } // build st int n2 = n >> LG; int lg = (n2 <= 1 ? 1 : std::bit_width<uint32_t>(n2 - 1)); st.resize(lg); st[0].resize(n2); for (int i = 0; i < n2; i++){ st[0][i] = suf[i << LG]; } for (int d = 0; d < lg - 1; d++){ int nsz = (int)(st[d].size()) - (1 << d); st[d + 1].resize(nsz); for (int i = 0; i < nsz; i++){ int x = st[d][i]; int y = st[d][i + (1 << d)]; st[d + 1][i] = (x < y ? x : y); } } } int st_prod(int l, int r){ if (l == r){ return std::numeric_limits<int>::max(); } int k = std::bit_width<uint32_t>(r - l) - 1; int x = st[k][l]; int y = st[k][r - (1 << k)]; return (x < y ? x : y); } int prod(int l, int r){ assert(l < r); r--; int x = l >> LG, y = r >> LG; if (x < y){ int p1 = suf[l]; int p2 = st_prod(x + 1, y); int p3 = pre[r]; return (p1 < p2 ? (p1 < p3 ? p1 : p3) : (p2 < p3 ? p2 : p3)); } int ret = a[l]; for (int i = l + 1; i <= r; i++){ if (ret > a[i]){ ret = a[i]; } } return ret; } int lca(int u, int v){ if (u == v) return u; u = down[u], v = down[v]; if (u > v) std::swap(u, v); return prod(u, v); } }; #line 2 "fastio.hpp" #line 4 "fastio.hpp" namespace nachia{ struct CInStream{ private: static const unsigned int INPUT_BUF_SIZE = 1 << 17; unsigned int p = INPUT_BUF_SIZE; static char Q[INPUT_BUF_SIZE]; public: using MyType = CInStream; char seekChar(){ if(p == INPUT_BUF_SIZE){ size_t len = fread(Q, 1, INPUT_BUF_SIZE, stdin); if(len != INPUT_BUF_SIZE) Q[len] = '\0'; p = 0; } return Q[p]; } void skipSpace(){ while(isspace(seekChar())) p++; } private: template<class T, int sp = 1> T nextUInt(){ if constexpr (sp) skipSpace(); T buf = 0; while(true){ char tmp = seekChar(); if('9' < tmp || tmp < '0') break; buf = buf * 10 + (tmp - '0'); p++; } return buf; } public: uint32_t nextU32(){ return nextUInt<uint32_t>(); } int32_t nextI32(){ skipSpace(); if(seekChar() == '-'){ p++; return (int32_t)(-nextUInt<uint32_t, 0>()); } return (int32_t)nextUInt<uint32_t, 0>(); } uint64_t nextU64(){ return nextUInt<uint64_t>();} int64_t nextI64(){ skipSpace(); if(seekChar() == '-'){ p++; return (int64_t)(-nextUInt<int64_t, 0>()); } return (int64_t)nextUInt<int64_t, 0>(); } template<class T> T nextInt(){ skipSpace(); if(seekChar() == '-'){ p++; return - nextUInt<T, 0>(); } return nextUInt<T, 0>(); } char nextChar(){ skipSpace(); char buf = seekChar(); p++; return buf; } std::string nextToken(){ skipSpace(); std::string buf; while(true){ char ch = seekChar(); if(isspace(ch) || ch == '\0') break; buf.push_back(ch); p++; } return buf; } MyType& operator>>(unsigned int& dest){ dest = nextU32(); return *this; } MyType& operator>>(int& dest){ dest = nextI32(); return *this; } MyType& operator>>(unsigned long& dest){ dest = nextU64(); return *this; } MyType& operator>>(long& dest){ dest = nextI64(); return *this; } MyType& operator>>(unsigned long long& dest){ dest = nextU64(); return *this; } MyType& operator>>(long long& dest){ dest = nextI64(); return *this; } MyType& operator>>(std::string& dest){ dest = nextToken(); return *this; } MyType& operator>>(char& dest){ dest = nextChar(); return *this; } } ncin; struct FastOutputTable{ char LZ[1000][4] = {}; char NLZ[1000][4] = {}; constexpr FastOutputTable(){ using u32 = uint_fast32_t; for(u32 d=0; d<1000; d++){ LZ[d][0] = ('0' + d / 100 % 10); LZ[d][1] = ('0' + d / 10 % 10); LZ[d][2] = ('0' + d / 1 % 10); LZ[d][3] = '\0'; } for(u32 d=0; d<1000; d++){ u32 i = 0; if(d >= 100) NLZ[d][i++] = ('0' + d / 100 % 10); if(d >= 10) NLZ[d][i++] = ('0' + d / 10 % 10); if(d >= 1) NLZ[d][i++] = ('0' + d / 1 % 10); NLZ[d][i++] = '\0'; } } }; struct COutStream{ private: using u32 = uint32_t; using u64 = uint64_t; using MyType = COutStream; static const u32 OUTPUT_BUF_SIZE = 1 << 17; static char Q[OUTPUT_BUF_SIZE]; static constexpr FastOutputTable TB = FastOutputTable(); u32 p = 0; static constexpr u32 P10(u32 d){ return d ? P10(d-1)*10 : 1; } static constexpr u64 P10L(u32 d){ return d ? P10L(d-1)*10 : 1; } template<class T, class U> static void Fil(T& m, U& l, U x){ m = l/x; l -= m*x; } public: void next_dig9(u32 x){ u32 y; Fil(y, x, P10(6)); nextCstr(TB.LZ[y]); Fil(y, x, P10(3)); nextCstr(TB.LZ[y]); nextCstr(TB.LZ[x]); } void nextChar(char c){ Q[p++] = c; if(p == OUTPUT_BUF_SIZE){ fwrite(Q, p, 1, stdout); p = 0; } } void nextEoln(){ nextChar('\n'); } void nextCstr(const char* s){ while(*s) nextChar(*(s++)); } void nextU32(uint32_t x){ u32 y = 0; if(x >= P10(9)){ Fil(y, x, P10(9)); nextCstr(TB.NLZ[y]); next_dig9(x); } else if(x >= P10(6)){ Fil(y, x, P10(6)); nextCstr(TB.NLZ[y]); Fil(y, x, P10(3)); nextCstr(TB.LZ[y]); nextCstr(TB.LZ[x]); } else if(x >= P10(3)){ Fil(y, x, P10(3)); nextCstr(TB.NLZ[y]); nextCstr(TB.LZ[x]); } else if(x >= 1) nextCstr(TB.NLZ[x]); else nextChar('0'); } void nextI32(int32_t x){ if(x >= 0) nextU32(x); else{ nextChar('-'); nextU32((u32)-x); } } void nextU64(uint64_t x){ u32 y = 0; if(x >= P10L(18)){ Fil(y, x, P10L(18)); nextU32(y); Fil(y, x, P10L(9)); next_dig9(y); next_dig9(x); } else if(x >= P10L(9)){ Fil(y, x, P10L(9)); nextU32(y); next_dig9(x); } else nextU32(x); } void nextI64(int64_t x){ if(x >= 0) nextU64(x); else{ nextChar('-'); nextU64((u64)-x); } } template<class T> void nextInt(T x){ if(x < 0){ nextChar('-'); x = -x; } if(!(0 < x)){ nextChar('0'); return; } std::string buf; while(0 < x){ buf.push_back('0' + (int)(x % 10)); x /= 10; } for(int i=(int)buf.size()-1; i>=0; i--){ nextChar(buf[i]); } } void writeToFile(bool flush = false){ fwrite(Q, p, 1, stdout); if(flush) fflush(stdout); p = 0; } COutStream(){ Q[0] = 0; } ~COutStream(){ writeToFile(); } MyType& operator<<(unsigned int tg){ nextU32(tg); return *this; } MyType& operator<<(unsigned long tg){ nextU64(tg); return *this; } MyType& operator<<(unsigned long long tg){ nextU64(tg); return *this; } MyType& operator<<(int tg){ nextI32(tg); return *this; } MyType& operator<<(long tg){ nextI64(tg); return *this; } MyType& operator<<(long long tg){ nextI64(tg); return *this; } MyType& operator<<(const std::string& tg){ nextCstr(tg.c_str()); return *this; } MyType& operator<<(const char* tg){ nextCstr(tg); return *this; } MyType& operator<<(char tg){ nextChar(tg); return *this; } } ncout; char CInStream::Q[INPUT_BUF_SIZE]; char COutStream::Q[OUTPUT_BUF_SIZE]; } // namespace nachia #line 95 "c.cpp" fast_lca fl({0}); int dep[MAX],parr[MAX]; vi G2[MAX]; void init(int u,int p){ for(int to:G2[u]){ if(to==p) continue; dep[to]=dep[u]+1; parr[to]=u; init(to,u); } } int lca(int a,int b){ return fl.lca(a,b); } int dd(int a,int b){ return dep[a]+dep[b]-dep[lca(a,b)]*2; } 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]]; } }; 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){ int d=dd(u,v); T[u].emplace_back(mp(v,d)); T[v].emplace_back(mp(u,d)); } using 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; } vi G3[MAX]; vi ss; int jun[MAX]; void mkmk(int u,int p){ jun[u]=si(ss); ss.pb(u); for(int to:G3[u]){ if(to==p) continue; mkmk(to,u); } } int main(){ std::ifstream in("text.txt"); std::cin.rdbuf(in.rdbuf()); cin.tie(0); ios::sync_with_stdio(false); using nachia::ncin, nachia::ncout; ncin>>N; vii E1,E2; for(int i=0;i<N-1;i++){ int a,b;ncin>>a>>b; a--;b--; E1.pb(mp(a,b)); } AT=AuxiliaryTree(N); for(int i=0;i<N-1;i++){ int a,b;ncin>>a>>b; a--;b--; G3[a].pb(b); G3[b].pb(a); E2.pb(mp(a,b)); } mkmk(0,-1); for(auto [a,b]:E1){ a=jun[a]; b=jun[b]; G[a].pb(b); G[b].pb(a); } for(auto [a,b]:E2){ a=jun[a]; b=jun[b]; G2[a].pb(b); G2[b].pb(a); AT.add_edge(a,b); } init(0,-1); //ncout<<"A\n"; vi parw(N); for(int i=0;i<N;i++){ parw[i]=parr[i]; } //ncout<<N<<" "<<si(parw)<<"\n"; //return 0; fl=fast_lca(parw); //ncout<<"B\n"; AT.build(); solve_subproblem(0,-1); ans*=2; ncout<<ans<<"\n"; }