제출 #1292607

#제출 시각아이디문제언어결과실행 시간메모리
1292607Minbaev공장들 (JOI14_factories)C++20
0 / 100
19 ms792 KiB
#include "factories.h" #include <bits/stdc++.h> using namespace std; using ll = long long; #define ar array struct Seg { int n; vector<ll> tree, lazy; Seg() : n(0) {} Seg(int _n) { init(_n); } void init(int _n){ n = _n; tree.assign(4*n+5, 0); lazy.assign(4*n+5, LLONG_MAX); } inline void apply(int v, int l, int r, ll x){ tree[v] = x * (r - l + 1); lazy[v] = x; } inline void push(int v, int l, int r){ if(lazy[v] == LLONG_MAX) return; if(l != r){ int m = (l + r) >> 1; apply(v<<1, l, m, lazy[v]); apply(v<<1|1, m+1, r, lazy[v]); } lazy[v] = LLONG_MAX; } void upd(int v, int l, int r, int ql, int qr, ll x){ if(ql > qr || r < ql || qr < l) return; if(ql <= l && r <= qr){ apply(v, l, r, x); return; } push(v, l, r); int m = (l + r) >> 1; upd(v<<1, l, m, ql, qr, x); upd(v<<1|1, m+1, r, ql, qr, x); tree[v] = tree[v<<1] + tree[v<<1|1]; } ll get(int v, int l, int r, int ql, int qr){ if(ql > qr || r < ql || qr < l) return 0; if(ql <= l && r <= qr){ return tree[v]; } push(v, l, r); int m = (l + r) >> 1; return get(v<<1, l, m, ql, qr) + get(v<<1|1, m+1, r, ql, qr); } // helpers void range_assign(int l, int r, ll x){ if(l>r) return; upd(1,1,n,l,r,x); } ll range_sum(int l, int r){ if(l>r) return 0; return get(1,1,n,l,r); } }; static int Nglob = 0; static vector<vector<pair<int,int>>> g; static vector<int> id_, id_rev, head, parent_, sz; static vector<ll> dep; static int timer_; static Seg seg; void dfs_hld(int u, int p){ parent_[u] = p; sz[u] = 1; for(auto &ed : g[u]){ int v = ed.first; int w = ed.second; if(v == p) continue; dep[v] = dep[u] + (ll)w; dfs_hld(v, u); sz[u] += sz[v]; } } void hld_build(int u, int p){ int heavy = -1; for(auto &ed : g[u]){ int v = ed.first; if(v == p) continue; if(heavy == -1 || sz[v] > sz[heavy]) heavy = v; } // assign id timer_++; id_[u] = timer_; id_rev[timer_] = u; if(heavy != -1){ head[heavy] = head[u]; hld_build(heavy, u); } for(auto &ed : g[u]){ int v = ed.first; if(v == p || v == heavy) continue; head[v] = v; hld_build(v, u); } } // helper: sum of enabled edges on chain head..x // note: edges are represented by positions id[node]; the edge parent->node sits at id[node] (root has no edge) inline ll chain_sum_edges(int h_id, int x_id){ // edges on path from node with id h_id to node with id x_id are positions (h_id+1 .. x_id) if(h_id + 1 > x_id) return 0; return seg.range_sum(h_id + 1, x_id); } // up(x): find top-most node of the component containing x when edges marked =1 int up_node(int x){ // if the node itself has no edges upward (i.e., path empty), we may return it while(true){ int h = head[x]; int hid = id_[h]; int xid = id_[x]; ll total = chain_sum_edges(hid, xid); if(total == (ll)(xid - hid)){ // whole chain from h..x is filled; try go above if(parent_[h] == -1) return h; x = parent_[h]; continue; } else { // binary search within [hid, xid] to find minimal pos pos such that edges pos+1..xid are all ones int L = hid, R = xid; while(L < R){ int M = (L + R) >> 1; ll s = chain_sum_edges(M, xid); if(s == (ll)(xid - M)) R = M; else L = M + 1; } return id_rev[L]; } } } // set all edges on path from root of chain to node x to value val (0 or 1) void set_path_up(int x, int val){ while(true){ int h = head[x]; int hid = id_[h]; int xid = id_[x]; if(hid + 1 <= xid) seg.range_assign(hid+1, xid, val); if(parent_[h] == -1) break; x = parent_[h]; } } // API functions required by grader void Init(int N, int A[], int B[], int D[]){ Nglob = N; g.clear(); g.resize(Nglob); id_.assign(Nglob, 0); id_rev.assign(Nglob+1, 0); // 1-based ids -> id_rev[1..N] head.assign(Nglob, 0); parent_.assign(Nglob, -1); sz.assign(Nglob, 0); dep.assign(Nglob, 0); timer_ = 0; // A,B,D length N-1 for(int i = 0; i < Nglob - 1; ++i){ int a = A[i], b = B[i], d = D[i]; // assume input nodes are 0-based as in JOI spec g[a].push_back({b, d}); g[b].push_back({a, d}); } // root at 0 dep[0] = 0; parent_[0] = -1; dfs_hld(0, -1); head[0] = 0; hld_build(0, -1); // seg tree size = N (we use positions 1..N) seg.init(Nglob); } long long Query(int S, int X[], int T, int Y[]){ // mark all chains from each X[i] to top (set edges = 1) for(int i = 0; i < S; ++i){ int v = X[i]; set_path_up(v, 1); } // for each Y find its top-most node u and distance from Y to u vector<pair<int,ll>> vs; vs.reserve(T); for(int i = 0; i < T; ++i){ int y = Y[i]; int u = up_node(y); ll dist = dep[y] - dep[u]; vs.emplace_back(u, dist); } // unmark X chains (restore edges = 0) for(int i = 0; i < S; ++i){ int v = X[i]; set_path_up(v, 0); } // reduce vs to minimal per u unordered_map<int,ll> best; best.reserve(vs.size()*2+5); for(auto &pr : vs){ int u = pr.first; ll d = pr.second; auto it = best.find(u); if(it == best.end()) best[u] = d; else if(d < it->second) it->second = d; } ll ans = LLONG_MAX; for(int i = 0; i < S; ++i){ int x = X[i]; int u = up_node(x); auto it = best.find(u); if(it == best.end()) continue; ll cand = (dep[x] - dep[u]) + it->second; if(cand < ans) ans = cand; } if(ans == LLONG_MAX) return -1; // if unreachable; problem statement may guarantee reachable, adapt if needed return ans; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...