Submission #1118586

#TimeUsernameProblemLanguageResultExecution timeMemory
1118586steveonalexTwo Currencies (JOI23_currencies)C++17
100 / 100
621 ms98056 KiB
#include <bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned long long ull; #define MASK(i) (1LL << (i)) #define GETBIT(mask, i) (((mask) >> (i)) & 1) #define ALL(v) (v).begin(), (v).end() ll max(ll a, ll b){return (a > b) ? a : b;} ll min(ll a, ll b){return (a < b) ? a : b;} ll LASTBIT(ll mask){return (mask) & (-mask);} long pop_cnt(ll mask){return __builtin_popcountll(mask);} long ctz(ll mask){return __builtin_ctzll(mask);} long clz(ll mask){return __builtin_clzll(mask);} long logOf(ll mask){return 63 - clz(mask);} mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count()); void debug(){cout.flush();} template <class T1, class T2> bool maximize(T1 &a, T2 b){ if (a < b) {a = b; return true;} return false; } template <class T1, class T2> bool minimize(T1 &a, T2 b){ if (a > b) {a = b; return true;} return false; } template <class T> void printArr(T& container, char separator = ' ', char finish = '\n'){ for(auto item: container) cout << item << separator; cout << finish; } template <class T> void remove_dup(vector<T> &a){ sort(ALL(a)); a.resize(unique(ALL(a)) - a.begin()); } struct PST{ struct Node{ int child[2], cnt; ll sum; Node(){memset(child, -1, sizeof child); sum = cnt = 0;} }; int L, R; vector<Node> a; vector<int> version; PST(int _L, int _R, int _n = 1){ L = _L, R = _R; a.reserve(_n); } void add_child(int &x){ x = a.size(); a.push_back(Node()); } void new_tree(){ version.push_back(a.size()); a.push_back(Node()); build_tree(L, R, version.back()); } void build_tree(int l, int r, int id){ if (l == r) return; int mid = (l + r) >> 1; add_child(a[id].child[0]); add_child(a[id].child[1]); build_tree(l, mid, a[id].child[0]); build_tree(mid + 1, r, a[id].child[1]); } void update(int i, pair<int, ll> val, int l, int r, int prev_id, int id){ a[id].cnt = a[prev_id].cnt + val.first; a[id].sum = a[prev_id].sum + val.second; if (l == r) { return; } int mid = (l + r) >> 1; a[id].child[0] = a[prev_id].child[0]; a[id].child[1] = a[prev_id].child[1]; if (i <= mid){ add_child(a[id].child[0]); update(i, val, l, mid, a[prev_id].child[0], a[id].child[0]); } else{ add_child(a[id].child[1]); update(i, val, mid + 1, r, a[prev_id].child[1], a[id].child[1]); } } void update(int i, pair<int, ll> val, int id = -1){ if (id == -1) id = version.back(); version.push_back(0); add_child(version.back()); update(i, val, L, R, id, version.back()); } array<ll, 3> walk(ll c, int id1, int id2, int id3){ array<ll, 3> ans = {0, 0, 0}; int l = L, r = R; ll cnt = 0, sum = 0; while(l < r){ int mid= (l + r) >> 1; if (a[a[id1].child[0]].sum + a[a[id2].child[0]].sum - 2*a[a[id3].child[0]].sum < c){ c -= a[a[id1].child[0]].sum + a[a[id2].child[0]].sum- 2*a[a[id3].child[0]].sum; cnt += a[a[id1].child[0]].cnt + a[a[id2].child[0]].cnt- 2*a[a[id3].child[0]].cnt; sum += a[a[id1].child[0]].sum + a[a[id2].child[0]].sum- 2*a[a[id3].child[0]].sum; id1 = a[id1].child[1]; id2 = a[id2].child[1]; id3 = a[id3].child[1]; l = mid + 1; } else{ id1 = a[id1].child[0]; id2 = a[id2].child[0]; id3 = a[id3].child[0]; r = mid; } } cnt += a[id1].cnt + a[id2].cnt- 2*a[id3].cnt; sum += a[id1].sum + a[id2].sum- 2*a[id3].sum; ans[0] = l; ans[1] = cnt; ans[2] = sum; return ans; } }; const int N = 1e5 + 69, LOG_N = 17; const int INF = 1e9 + 69; int n, m, q; vector<pair<int, int>> graph[N]; vector<ll> lmao[N]; vector<int> b; int state[N], g[N]; int h[N], parent[N][LOG_N]; void dfs(int u, int p, int cur, PST &st){ h[u] = h[p] + 1; for(int j = 1; MASK(j) < h[u]; ++j) parent[u][j] = parent[parent[u][j-1]][j-1]; state[u] = cur; for(pair<int, int> v: graph[u]) if (v.first != p){ parent[v.first][0] = u; g[v.first] = g[u] + lmao[v.second].size(); if (lmao[v.second].empty()){ dfs(v.first, u, cur, st); } else{ int _cur = cur; for(ll j: lmao[v.second]){ int idx = lower_bound(ALL(b), j) - b.begin(); st.update(idx, {1, j}, _cur); _cur = st.version.back(); } dfs(v.first, u, _cur, st); } } } int LCA(int u, int v){ if (h[u] < h[v]) swap(u, v); int diff = h[u] - h[v]; for(int j = 0; j < LOG_N; ++j) if (GETBIT(diff, j)) u = parent[u][j]; if (u == v) return u; for(int j = LOG_N - 1; j>=0; --j) if (parent[u][j] != parent[v][j]){ u = parent[u][j]; v = parent[v][j]; } return parent[u][0]; } int main(){ ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin >> n >> m >> q; for(int i= 1; i<n; ++i){ int u, v; cin >> u >> v; graph[u].push_back({v, i}); graph[v].push_back({u, i}); } for(int i = 0; i<m; ++i){ int p, k; cin >> p >> k; lmao[p].push_back(k); b.push_back(k); } b.push_back(INF); remove_dup(b); m = b.size(); PST st(0, m-1, n * 20); st.new_tree(); dfs(1, 0, 0, st); while(q--){ ll u, v, x, y; cin >> u >> v >> x >> y; int lck = LCA(u, v); array<ll, 3> ans = st.walk(y, state[u], state[v], state[lck]); int gold_cnt = g[u] + g[v] - 2 * g[lck]; if (ans[2] <= y){ gold_cnt -= ans[1]; } else{ ll diff = ans[2] - y; if (diff % b[ans[0]] == 0) diff /= b[ans[0]]; else diff = diff / b[ans[0]] + 1; gold_cnt -= ans[1] - diff; } if (gold_cnt <= x) cout << x - gold_cnt << "\n"; else cout << -1 << "\n"; } return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...