제출 #1196386

#제출 시각아이디문제언어결과실행 시간메모리
1196386Szil공장들 (JOI14_factories)C++20
100 / 100
5508 ms150668 KiB
#include "factories.h" #include <bits/stdc++.h> using namespace std; using ll = long long; const int K = 20; const ll INF = 1e16; vector<vector<pair<int, ll>>> g; vector<int> tin, tout, par; vector<ll> depth, closest; vector<vector<int>> up; int timer, n; void dfs(int u, int p = -1, ll d = 0) { tin[u] = timer++; depth[u] = d; for (auto [v, w] : g[u]) { if (v == p) continue; up[v][0] = u; dfs(v, u, d + w); } tout[u] = timer++; } bool is_ancestor(int u, int v) { return tin[u] <= tin[v] && tout[v] <= tout[u]; } void preprocess_lca() { for (int k = 1; k < K; k++) { for (int i = 1; i <= n; i++) { up[i][k] = up[up[i][k-1]][k-1]; } } } int lca(int u, int v) { if (is_ancestor(u, v)) return u; if (is_ancestor(v, u)) return v; for (int i = K-1; i >= 0; i--) { if (up[u][i] && !is_ancestor(up[u][i], v)) u = up[u][i]; } return up[u][0]; } ll calc_dist(int u, int v) { int x = lca(u, v); return depth[u] + depth[v] - 2 * depth[x]; } void build_centroid_tree() { par = vector<int>(n+1); vector<int> siz(n+1); vector<bool> vis(n+1); auto calc_siz = [&](auto &&self, int u, int p = -1) -> void { siz[u] = 1; for (auto [v, w] : g[u]) { if (v == p || vis[v]) continue; self(self, v, u); siz[u] += siz[v]; } }; auto find_centroid = [&](auto &&self, int u, int th, int p = -1) -> int { for (auto [v, w] : g[u]) { if (v == p || vis[v]) continue; if (siz[v] > th) return self(self, v, th, u); } return u; }; auto decomp = [&](auto &&self, int u) -> int { calc_siz(calc_siz, u); u = find_centroid(find_centroid, u, siz[u]/2); vis[u] = 1; for (auto [v, w] : g[u]) { if (!vis[v]) { int x = self(self, v); par[x] = u; } } return u; }; decomp(decomp, 1); } void Init(int N, int A[], int B[], int D[]) { n = N; g = vector<vector<pair<int, ll>>>(n+1); tin = vector<int>(n+1); tout = vector<int>(n+1); depth = vector<ll>(n+1); closest = vector<ll>(n+1, INF); up = vector<vector<int>>(n+1, vector<int>(K)); timer = 1; for (int i = 0; i < n-1; i++) { g[A[i]+1].emplace_back(B[i]+1, D[i]); g[B[i]+1].emplace_back(A[i]+1, D[i]); } dfs(1); preprocess_lca(); build_centroid_tree(); } long long Query(int S, int X[], int T, int Y[]) { // ll ans = INF; // for (int i = 0; i < S; i++) { // for (int j = 0; j < T; j++) { // cerr << X[i]+1 << " " << Y[j]+1 << ": " << calc_dist(X[i]+1, Y[j]+1) << endl; // ans = min(ans, calc_dist(X[i]+1, Y[j]+1)); // } // } for (int i = 0; i < S; i++) { int u = X[i]+1; int v = u; while (v) { closest[v] = min(closest[v], calc_dist(v, u)); v = par[v]; } } ll ans = INF; for (int i = 0; i < T; i++) { int u = Y[i]+1; int v = u; while (v) { ans = min(ans, closest[v] + calc_dist(u, v)); v = par[v]; } } for (int i = 0; i < S; i++) { int u = X[i]+1; int v = u; while (v) { closest[v] = INF; v = par[v]; } } return ans; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...