Submission #1306817

#TimeUsernameProblemLanguageResultExecution timeMemory
1306817mikolaj00Two Currencies (JOI23_currencies)C++20
100 / 100
3090 ms38848 KiB
#include <bits/stdc++.h> using namespace std; using ll = long long; int ceil_lg(int k) { int res = __lg(k); if (1<<res < k) res++; return res; } struct SegTree { SegTree(int size) { int k = 1<<(ceil_lg(size)+1); arr.resize(k); lazy.resize(k); } void push(int v) { arr[v<<1] += lazy[v]; lazy[v<<1] += lazy[v]; arr[(v<<1)+1] += lazy[v]; lazy[(v<<1)+1] += lazy[v]; lazy[v] = 0; } void update(int l, int r, ll val, int v = 1, int a = 0, int b = -1) { if (b == -1) b = (arr.size()>>1)-1; if (b < l || a > r) return; else if (a >= l && b <= r) { lazy[v] += val; arr[v] += val; } else { int mid = (a+b)>>1; push(v); update(l, r, val, v<<1, a, mid); update(l, r, val, (v<<1)+1, mid+1, b); } } ll query(int k, int v = 1, int a = 0, int b = -1) { if (b == -1) b = (arr.size()>>1)-1; if (b < k || a > k) return 0; else if (a == k && b == k) return arr[v]; else { int mid = (a+b)>>1; push(v); return query(k, v<<1, a, mid) + query(k, (v<<1)+1, mid+1, b); } } vector<ll> arr; vector<ll> lazy; }; vector<vector<int>> g; vector<int> pre, post; vector<int> dep; vector<vector<int>> up; vector<pair<int, int>> edges; struct Checkpoint { int v; ll c; friend bool operator<(Checkpoint const& c1, Checkpoint const& c2) { return c1.c < c2.c; } }; struct Query { int s, t; ll x, y; int l, r; int idx; friend bool operator<(Query const& q1, Query const& q2) { return (q1.l + q1.r + 1)>>1 < (q2.l + q2.r + 1)>>1; } }; int lca(int a, int b) { if (dep[a] < dep[b]) swap(a, b); for (int i = up[a].size()-1; i >= 0; i--) { int a_ = up[a][i]; if (dep[a_] >= dep[b]) a = a_; } if (a == b) return a; for (int i = up[a].size()-1; i >= 0; i--) { int a_ = up[a][i], b_ = up[b][i]; if (a_ != b_) { a = a_; b = b_; } } return up[a][0]; } int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); int n, m, q; cin >> n >> m >> q; g.resize(n+1); pre.resize(n+1); post.resize(n+1); dep.resize(n+1); up.resize(n+1, vector<int>(__lg(n)+1)); edges.resize(n-1); for (int i = 0; i < n-1; i++) { int a, b; cin >> a >> b; edges[i] = {a, b}; g[a].push_back(b); g[b].push_back(a); } dep[0] = -1; int time = 0; function<void(int, int)> dfs = [&](int u, int p) -> void { pre[u] = time++; dep[u] = dep[p] + 1; up[u][0] = p; for (int i = 1; i < up[u].size(); i++) up[u][i] = up[up[u][i-1]][i-1]; for (auto v : g[u]) if (v != p) dfs(v, u); post[u] = time; }; dfs(1, 0); vector<Checkpoint> checkpoints(m); for (int i = 0; i < m; i++) { int p, c; cin >> p >> c; auto[a, b] = edges[p-1]; if (pre[a] < pre[b]) checkpoints[i] = {b, c}; else checkpoints[i] = {a, c}; } sort(checkpoints.begin(), checkpoints.end()); vector<Query> queries(q); for (int i = 0; i < q; i++) { cin >> queries[i].s >> queries[i].t >> queries[i].x >> queries[i].y; queries[i].l = 0; queries[i].r = m; queries[i].idx = i; } while (true) { vector<Query*> cur_queries; for (auto& q : queries) if (q.l != q.r) cur_queries.push_back(&q); if (cur_queries.empty()) break; // cout << cur_queries[0]->l << ' ' << cur_queries[0]->r << '\n'; sort(cur_queries.begin(), cur_queries.end(), [](Query* q1, Query* q2) -> bool {return *q1 < *q2;}); int p = 0; SegTree st(n); for (int i = 0; i <= m; i++) { for (; p < cur_queries.size(); p++) { Query& q = *cur_queries[p]; int mid = (q.l + q.r + 1)>>1; if (mid > i) break; int l = lca(q.s, q.t); ll val = st.query(pre[q.s]) + st.query(pre[q.t]) - (st.query(pre[l])<<1); if (val <= q.y) q.l = mid; else q.r = mid-1; } if (i < m) { Checkpoint c = checkpoints[i]; st.update(pre[c.v], post[c.v]-1, c.c); } // for (int i = 0; i < n; i++) // cout << st.query(i) << ' '; // cout << '\n'; } } SegTree st(n); vector<int> ans(q); sort(queries.rbegin(), queries.rend()); int p = 0; for (int i = m; i >= 0; i--) { if (i < m) { Checkpoint c = checkpoints[i]; st.update(pre[c.v], post[c.v]-1, 1); } for (; p < queries.size(); p++) { Query q = queries[p]; if (q.l < i) break; int l = lca(q.s, q.t); ans[q.idx] = q.x - (st.query(pre[q.s]) + st.query(pre[q.t]) - (st.query(pre[l])<<1)); } } for (int i = 0; i < q; i++) cout << (ans[i] >= 0 ? ans[i] : -1) << '\n'; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...