제출 #941456

#제출 시각아이디문제언어결과실행 시간메모리
941456TAhmed33Two Currencies (JOI23_currencies)C++98
100 / 100
3237 ms74064 KiB
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int MAXN = 1e5 + 25; #define mid ((l + r) >> 1) #define tl (node + 1) #define tr (node + 2 * (mid - l + 1)) struct SegmentTree { ll tree[MAXN << 1]; void init () { for (int i = 1; i < 2 * MAXN; i++) tree[i] = 0; } void update (int l, int r, int a, int b, int c, int node) { if (l > b || r < a) return; if (l >= a && r <= b) { tree[node] += c; return; } update(l, mid, a, b, c, tl); update(mid + 1, r, a, b, c, tr); } ll get (int l, int r, int a, int node) { if (l == r) return tree[node]; if (a <= mid) return tree[node] + get(l, mid, a, tl); return tree[node] + get(mid + 1, r, a, tr); } } cur, cur3; vector <int> adj[MAXN]; int n, m, q; pair <ll, ll> dd[MAXN]; array <ll, 5> queries[MAXN]; ll ans[MAXN]; ll low[MAXN], high[MAXN]; int dep[MAXN], dp[18][MAXN]; void calc (int pos, int par) { dp[0][pos] = par; for (auto j : adj[pos]) { if (j != par) { dep[j] = 1 + dep[pos]; calc(j, pos); } } } int jump (int a, int b) { for (int i = 17; i >= 0; i--) if (b & (1 << i)) a = dp[i][a]; return a; } int lca (int a, int b) { if (dep[a] > dep[b]) swap(a, b); b = jump(b, dep[b] - dep[a]); if (a == b) return a; for (int i = 17; i >= 0; i--) { int x = dp[i][a], y = dp[i][b]; if (x && y && x != y) { a = x, b = y; } } return dp[0][a]; } pair <int, int> edges[MAXN]; ll cur2[MAXN], cur4[MAXN], init[MAXN], finn[MAXN]; vector <pair <ll, ll>> updates[MAXN]; vector <array <ll, 4>> updates2[MAXN]; void dfs (int pos, int par) { for (auto j : updates[pos]) { cur.update(1, m, j.first, m, j.second, 1); cur3.update(1, m, j.first, m, 1, 1); } for (auto j : updates2[pos]) { ll z = cur.get(1, m, j[1], 1); ll z2 = cur3.get(1, m, j[1], 1); if (j[2]) { cur2[j[0]] += z; cur4[j[0]] += z2; } else { cur2[j[0]] -= z; cur4[j[0]] -= z2; } } for (auto j : adj[pos]) { if (j != par) { dfs(j, pos); } } for (auto j : updates[pos]) { cur.update(1, m, j.first, m, -j.second, 1); cur3.update(1, m, j.first, m, -1, 1); } } int main () { ios::sync_with_stdio(0); cin.tie(0); cin >> n >> m >> q; for (int i = 1; i < n; i++) { int x, y; cin >> x >> y; adj[x].push_back(y); adj[y].push_back(x); edges[i] = {x, y}; } calc(1, 0); for (int i = 1; i < 18; i++) { for (int j = 1; j <= n; j++) { dp[i][j] = dp[i - 1][dp[i - 1][j]]; } } for (int i = 1; i < n; i++) { if (dep[edges[i].first] < dep[edges[i].second]) { swap(edges[i].first, edges[i].second); } } for (int i = 1; i <= m; i++) { ll x, y; cin >> x >> y; dd[i] = {x, y}; } sort(dd + 1, dd + m + 1, [&] (pair <int, int> x, pair <int, int> y) { return x.second < y.second; }); for (int i = 1; i <= m; i++) { updates[edges[dd[i].first].first].push_back({i, dd[i].second}); } for (int i = 1; i <= q; i++) { ll w, x, y, z; cin >> w >> x >> y >> z; queries[i] = {w, x, lca(w, x), z, y}; } for (int i = 1; i <= q; i++) { low[i] = 1, high[i] = m, ans[i] = 0; } { cur.init(); cur3.init(); for (int i = 1; i <= n; i++) { updates2[i].clear(); } for (int i = 1; i <= q; i++) { cur2[i] = 0; cur4[i] = 0; updates2[queries[i][2]].push_back({i, m, 0}); updates2[queries[i][2]].push_back({i, m, 0}); updates2[queries[i][0]].push_back({i, m, 1}); updates2[queries[i][1]].push_back({i, m, 1}); } dfs(1, -1); for (int i = 1; i <= q; i++) { init[i] = cur4[i]; } } for (int iter = 1; iter <= 18; iter++) { cur.init(); cur3.init(); for (int i = 1; i <= n; i++) { updates2[i].clear(); } for (int i = 1; i <= q; i++) { if (low[i] > high[i]) continue; cur2[i] = 0; cur4[i] = 0; ll mid2 = (low[i] + high[i]) / 2; updates2[queries[i][2]].push_back({i, mid2, 0}); updates2[queries[i][2]].push_back({i, mid2, 0}); updates2[queries[i][0]].push_back({i, mid2, 1}); updates2[queries[i][1]].push_back({i, mid2, 1}); } dfs(1, -1); for (int i = 1; i <= q; i++) { if (low[i] > high[i]) continue; ll mid2 = (low[i] + high[i]) / 2; if (cur2[i] <= queries[i][3]) { low[i] = mid2 + 1; ans[i] = mid2; finn[i] = cur4[i]; } else { high[i] = mid2 - 1; } } } for (int i = 1; i <= q; i++) { //cout << i << ": " << init[i] << " " << finn[i] << '\n'; if (init[i] - finn[i] <= queries[i][4]) { cout << queries[i][4] - init[i] + finn[i] << '\n'; } else { cout << "-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...