제출 #1287503

#제출 시각아이디문제언어결과실행 시간메모리
1287503Ice_manRace (IOI11_race)C++17
100 / 100
317 ms77696 KiB
/** ____ ____ ____ __________________ ____ ____ ____ ||I || ||c || ||e || || || ||M || ||a || ||n || ||__|| ||__|| ||__|| ||________________|| ||__|| ||__|| ||__|| |/__\| |/__\| |/__\| |/________________\| |/__\| |/__\| |/__\| */ #include <iostream> #include <vector> #include <map> #include "race.h" #define maxn 500005 #define PB push_back #define X first #define Y second typedef long long ll; typedef std::pair<ll,ll> pll; const ll INF = (ll)4e18; std::vector<pll> v[maxn]; int n, k; ll ans; ll sumv[maxn]; int distv[maxn]; struct dsu { struct component { int par, sz; std::map<ll,ll> store; void init(int x) { par = x; sz = 1; store.clear(); } void _swap(component &other) { std::swap(sz, other.sz); store.swap(other.store); } void insert_min(ll key, ll val) { auto it = store.find(key); if(it == store.end()) store.emplace(key, val); else it->second = std::min(it->second, val); } ll get(ll key) const { auto it = store.find(key); if(it != store.end()) return it->second; return (ll)4e18; } }; std::vector<component> un; void init(int sz) { un.resize(sz + 1); for(int i = 1; i <= n; ++i) un[i].init(i); } }; dsu uni; // precompute sums and depths and fill each node's map with (sum -> depth) void precomp(int u, int p, ll acc, int depth) { sumv[u] = acc; distv[u] = depth; // store sum->depth in the component map uni.un[u].store[acc] = depth; for(auto &ed : v[u]) { int to = (int)ed.X; ll w = ed.Y; if(to == p) continue; precomp(to, u, acc + w, depth + 1); } } // small-to-large merging using component maps stored in uni.un[] void small_to_large_merge(int u, int p) { ll target = (ll)k + 2LL * sumv[u]; for(auto &ed : v[u]) { int to = (int)ed.X; if(to == p) continue; small_to_large_merge(to, u); // ensure we merge smaller into larger: if child's map bigger, swap them if(uni.un[to].store.size() > uni.un[u].store.size()) { uni.un[to]._swap(uni.un[u]); } // for every entry in child's map check for complement in parent's map for(auto &pr : uni.un[to].store) { ll keyB = pr.X; ll valB = pr.Y; ll need = target - keyB; auto it = uni.un[u].store.find(need); if(it != uni.un[u].store.end()) { ll cand = it->second + valB - 2LL * distv[u]; if(cand < ans) ans = cand; } } // merge child's entries into parent's map (keeping minimal depth) for(auto &pr : uni.un[to].store) { ll keyB = pr.X; ll valB = pr.Y; auto it2 = uni.un[u].store.find(keyB); if(it2 == uni.un[u].store.end()) uni.un[u].store.emplace(keyB, valB); else it2->second = std::min(it2->second, valB); } // clear child's map to free memory uni.un[to].store.clear(); } } int best_path(int N, int K, int h[][2], int L[]) { n = N; k = K; ans = INF; // clear adjacency for(int i = 1; i <= n; ++i) v[i].clear(); // build graph (input h is 0-based; we use 1-based internal) for(int i = 0; i < n - 1; ++i) { int a = h[i][0] + 1; int b = h[i][1] + 1; ll w = L[i]; v[a].PB({b, w}); v[b].PB({a, w}); } uni.init(n + 5); // root at 1 (same as editorial rooted at 0 but adjusted for 1-based) precomp(1, 0, 0LL, 0); small_to_large_merge(1, 0); if(ans == INF) return -1; return (int)ans; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...