제출 #1117296

#제출 시각아이디문제언어결과실행 시간메모리
1117296gdragonValley (BOI19_valley)C++17
100 / 100
385 ms32840 KiB
#include <bits/stdc++.h> using namespace std; #define TASK "long" #define fi first #define se second #define ll long long #define pb push_back #define ALL(x) (x).begin(), (x).end() #define GETBIT(mask, i) ((mask) >> (i) & 1) #define MASK(i) ((1LL) << (i)) #define SZ(x) ((int)(x).size()) #define mp make_pair #define CNTBIT(mask) __builtin_popcount(mask) template<class X, class Y> bool maximize(X &x, Y y){ if (x < y) {x = y; return true;} return false;}; template<class X, class Y> bool minimize(X &x, Y y){ if (x > y) {x = y; return true;} return false;}; typedef pair<int, int> ii; const int N = 1e5 + 5; const long long INF = (long long)1e18 + 7; const int mod = 1e9 + 7; struct Fenwick { int n; vector<long long> v; Fenwick(int _n = 0) { n = _n; v.assign(n + 2, 0); } void update(int x, int c) { for(; x <= n; x += x & -x) v[x] += c; } long long get(int x) { long long ans = 0; for(; x > 0; x -= x & -x) ans += v[x]; return ans; } long long get(int l, int r) { return (get(r) - get(l - 1)); } } fw; struct SegTree { int n; vector<long long> st, lz; SegTree(int _n = 0) { n = _n; st.assign(4 * n + 5, INF); lz.assign(4 * n + 5, 0); } void down(int id) { long long &t = lz[id]; if (t == 0) return; for(int i = (id<<1); i <= (id<<1|1); i++) { st[i] += (st[i] == INF ? 0 : t); lz[i] += t; } t = 0; } void update(int id, int l, int r, int u, int v, int c) { if (u > r || v < l) return; if (u <= l && r <= v) { // if (c == 2) cerr << "L R : " << l << ' ' << r << endl; st[id] += (st[id] == INF ? 0 : c); lz[id] += c; return; } down(id); int mid = (l + r) >> 1; update(id<<1, l, mid, u, v, c); update(id<<1|1, mid + 1, r, u, v, c); st[id] = min(st[id<<1], st[id<<1|1]); } void update(int l, int r, int c) { // if (c == 2) cout << l << ' ' << r << endl; if (c >= INF) return; return update(1, 1, n, l, r, c); } void update1(int id, int l, int r, int p, long long c) { if (l == r) { st[id] = c; return; } down(id); int mid = (l + r) >> 1; if (p <= mid) update1(id<<1, l, mid, p, c); else update1(id<<1|1, mid + 1, r, p, c); st[id] = min(st[id<<1], st[id<<1|1]); } void update1(int p, long long c) { if (c >= INF) return; return update1(1, 1, n, p, c); } long long get(int id, int l, int r, int u, int v) { if (u > r || v < l) return INF; if (u <= l && r <= v) return st[id]; down(id); int mid = (l + r) >> 1; return min(get(id<<1, l, mid, u, v), get(id<<1|1, mid + 1, r, u, v)); } long long get(int l, int r) { return get(1, 1, n, l, r); } } it; int n, q, numShop, root; int tin[N], tout[N], high[N], head[N], sz[N], par[N]; bool isShop[N]; pair<long long, int> f1[N], f2[N]; pair<int, int> e[N]; vector<pair<int, int>> adj[N], queries[N]; vector<int> shops; long long ans[N]; void read() { cin >> n >> numShop >> q >> root; for(int i = 1; i < n; i++) { int u, v, c; cin >> u >> v >> c; adj[u].push_back({v, c}); adj[v].push_back({u, c}); e[i] = {u, v}; } shops.resize(numShop); for(auto&i : shops) { cin >> i; isShop[i] = 1; } } int timer = 0; void dfs(int u, int p) { sz[u] = 1; par[u] = p; for(auto& i: adj[u]) { int v = i.fi; if (v == p) continue; high[v] = high[u] + 1; dfs(v, u); sz[u] += sz[v]; } } bool isChild(int u, int p) { return tin[u] >= tin[p] && tin[u] <= tout[p]; } void hld(int u, int p, int top, int w) { tin[u] = ++timer; head[u] = top; // cerr << u << ' ' << head[u] << endl; // if (p != -1) weight.update(tin[u], w); int bigC = -1, bigW = -1; for(auto &i: adj[u]) { int v = i.fi; if (v == p) continue; if (bigC == -1 || sz[bigC] < sz[v]) { bigC = v; bigW = i.se; } } if (bigC == -1) { tout[u] = timer; return; } hld(bigC, u, top, bigW); for(auto &i: adj[u]) { int v = i.fi; if (v == p || v == bigC) continue; hld(v, u, v, i.se); } tout[u] = timer; } void update(int u, int v, int c) { while(head[u] != head[v]) { if (high[head[u]] < high[head[v]]) swap(u, v); it.update(tin[head[u]], tin[u], c); u = par[head[u]]; } if (high[u] > high[v]) swap(u, v); it.update(tin[u], tin[v], c); } long long get(int u, int v) { // if (high[u] < high[v]) swap(u, v); long long ans = INF; // cerr << "DB: " << u << ' ' << v << endl; while(head[u] != head[v]) { if (high[head[u]] < high[head[v]]) swap(u, v); // cerr << it.get(tin[head[u]], tin[u]) << endl; ans = min(ans, it.get(tin[head[u]], tin[u])); // ans += weight.get(tin[head[u]], tin[u]); // cerr << head[u] << ' ' << u << endl; u = par[head[u]]; } if (high[u] > high[v]) swap(u, v); ans = min(ans, it.get(tin[u], tin[v])); // ans += weight.get(tin[u] + 1, tin[v]); return ans; } long long calF(int u, int p) { f1[u] = f2[u] = {INF, 0}; if (isShop[u]) f1[u] = {0, u}; for(auto &i: adj[u]) { int v = i.fi, c = i.se; if (v == p) continue; long long val = calF(v, u) + c; if (f1[u].fi > val) { f2[u] = f1[u]; f1[u] = mp(val, v); } else { if (minimize(f2[u].fi, val)) f2[u].se = v; } } // cerr << u << ' ' << f1[u].fi << ' ' << f1[u].se << endl; return f1[u].fi; } void calQuery(int u, int p) { for(auto [v, id]: queries[u]) { ans[id] = f1[u].fi; // cerr << "ANS: " << u << ' ' << f1[u].fi << endl; ans[id] = min(ans[id], get(v, u)); // cerr << id << ' ' << u << ' ' << v << endl; } for(auto [v, c]: adj[u]) { if (v == p) continue; if (f1[u].fi == 0) { // cerr << u << endl; it.update1(tin[u], 0); // cerr << u << ' ' << v << ' ' << 0 << endl; } else { if (v == f1[u].se) { it.update1(tin[u], f2[u].fi); // cerr << u << ' ' << v << ' ' << f2[u].fi << endl; } else { it.update1(tin[u], f1[u].fi); // cerr << u << ' ' << v << ' ' << f1[u].fi << endl; } } // cerr << u << ' ' << v << ' ' << c << endl; // if (v == 5) cerr << "ANS: " << it.get(tin[3], tout[3]) << endl; // cerr << "SEQ: " << tin[root] << ' ' << tin[u] << ' ' << c << endl; update(root, u, c); calQuery(v, u); update(root, u, -c); // cerr << -c << endl; } } void sub1() { fw = Fenwick(n); dfs(root, -1); hld(root, -1, root, 0); for(int shop: shops) fw.update(tin[shop], 1); for(int i = 1; i <= q; i++) { int road, node; cin >> road >> node; int u = e[road].fi, v = e[road].se; if (high[u] > high[v]) swap(u, v); if (isChild(node, v)) { if (fw.get(tin[v], tout[v]) == 0) { // cout << "oo\n"; ans[i] = INF; continue; } if (numShop == n) { ans[i] = 0; // cout << 0 << endl; continue; } queries[node].push_back({v, i}); // long long ans = INF; // for(int shop: shops) if (isChild(shop, v)) { // ans = min(ans, get(shop, node)); // } // cout << ans << endl; } else { // cout << "escaped\n"; ans[i] = -1; } } calF(root, -1); // for(int i = 1; i <= n; i++) cout << f1[i].fi << ' ' << f1[i].se << ' ' << f2[i].fi << ' ' << f2[i].se << endl; // cerr << f1[3].fi << ' ' << f1[3].se << endl; it = SegTree(n); calQuery(root, -1); for(int i = 1; i <= q; i++) { if (ans[i] == INF) cout << "oo"; else if (ans[i] == -1) cout << "escaped"; else cout << ans[i]; cout << endl; } } void solve() { sub1(); } signed main() { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); if (fopen(TASK".inp", "r")) { freopen(TASK".inp", "r", stdin); freopen(TASK".out", "w", stdout); } int test = 1; // cin >> test; while(test--) { read(); solve(); } return 0; }

컴파일 시 표준 에러 (stderr) 메시지

valley.cpp: In function 'int main()':
valley.cpp:292:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  292 |         freopen(TASK".inp", "r", stdin);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
valley.cpp:293:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  293 |         freopen(TASK".out", "w", stdout);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...