Submission #734378

#TimeUsernameProblemLanguageResultExecution timeMemory
734378NeroZeinTwo Currencies (JOI23_currencies)C++17
100 / 100
4807 ms45536 KiB
#include "bits/stdc++.h" #define int long long using namespace std; #ifdef Nero #include "Deb.h" #else #define deb(...) #endif struct queries { int u, v, gold, silver; }; const int Log = 18; const int N = 100005; int n, m, q; vector<int> g[N]; pair<int,int> e[N]; pair<int,int> ch[N]; int idd; int up[Log][N]; int in[N], out[N], dep[N]; void Dfs (int v, int p) { in[v] = ++idd; for (int u : g[v]) { if (u == p) continue; dep[u] = dep[v] + 1; up[0][u] = v; for (int i = 1; i < Log; ++i) { up[i][u] = up[i - 1][up[i - 1][u]]; } Dfs(u, v); } out[v] = idd; } int Lca (int u, int v) { if (dep[u] < dep[v]) swap(u, v); for (int i = 0; i < Log; ++i) { if ((dep[u] - dep[v]) >> i & 1) { u = up[i][u]; } } if (u == v) { return u; } for (int i = Log - 1; i >= 0; --i) { if (up[i][u] != up[i][v]) { u = up[i][u], v = up[i][v]; } } return up[0][u]; } int tree[N]; void upd (int id, int v) { while (id < N) { tree[id] += v; id += id & -id; } } void upd (int l, int r, int v) { upd(l, v); upd(r + 1, -v); } int qry (int id) { int ret = 0; while (id) { ret += tree[id]; id -= id & -id; } return ret; } int getSum (int u, int v) { return qry(in[u]) + qry(in[v]) - 2 * qry(in[Lca(u, v)]); } void addEdge (int i, bool weighted) { int u = e[ch[i].first].first, v = e[ch[i].first].second; if (dep[u] < dep[v]) swap(u, v); if (weighted) { upd(in[u], out[u], ch[i].second); } else { upd(in[u], out[u], 1); } } int ans[N]; int L[N], R[N]; pair<int,int> Mid[N]; signed main(){ ios::sync_with_stdio(false); cin.tie(nullptr); cin >> n >> m >> q; for (int i = 0; i < n - 1; ++i) { int u, v; cin >> u >> v; g[u].push_back(v); g[v].push_back(u); e[i] = {u, v}; } Dfs(1, 1); for (int i = 0; i < m; ++i) { int p, c; cin >> p >> c; ch[i] = {p - 1, c}; addEdge(i, 0); } vector<queries> qs(q); for (int i = 0; i < q; ++i) { int u, v, gold, silver; cin >> u >> v >> gold >> silver; qs[i] = {u, v, gold, silver}; ans[i] = getSum(u, v); } sort(ch, ch + m, [&](pair<int,int>& a, pair<int,int>& b) { return a.second < b.second; }); for (int i = 0; i < q; ++i) { L[i] = -1, R[i] = m - 1; } while (true) { memset(tree, 0, sizeof tree); bool changed = false; for (int i = 0; i < q; ++i) { if (L[i] != R[i]) { Mid[i] = make_pair((L[i] + R[i] + 1) >> 1, i); changed = true; } else { Mid[i] = make_pair(L[i], i); } } sort(Mid, Mid + q); int p = 0; if (!changed) { for (int i = 0; i < q; ++i) { while (p <= Mid[i].first) { addEdge(p, 0); p++; } ans[Mid[i].second] = qs[Mid[i].second].gold - (ans[Mid[i].second] - getSum(qs[Mid[i].second].u, qs[Mid[i].second].v)); } break; } for (int i = 0; i < q; ++i) { while (p <= Mid[i].first) { addEdge(p, 1); p++; } int id = Mid[i].second; if (getSum(qs[id].u, qs[id].v) <= qs[id].silver) { L[id] = Mid[i].first; } else { R[id] = Mid[i].first - 1; } } } for (int i = 0; i < q; ++i) { cout << max(-1LL, ans[i]) << '\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...