Submission #1250883

#TimeUsernameProblemLanguageResultExecution timeMemory
1250883chikien2009Two Currencies (JOI23_currencies)C++20
0 / 100
3 ms5192 KiB
#include <bits/stdc++.h> using namespace std; void setup() { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); } struct NODE { int l = 0, r = 0, num = 0; long long sum = 0; }; struct PERSISTENT_SEGMENT_TREE { int sz = 1; // use tree[0] as a virtual node store nothing NODE tree[2000000]; inline void Update(int &ind, int l, int r, int x, int v) { if (r < x || x < l) { return; } tree[sz] = tree[ind]; ind = sz++; tree[ind].num++; tree[ind].sum += v; if (l < r) { int m = (l + r) >> 1; Update(tree[ind].l, l, m, x, v); Update(tree[ind].r, m + 1, r, x, v); } } inline int Num(int x, int y, int z) { return tree[x].num + tree[y].num - 2 * tree[z].num; } inline long long Sum(int x, int y, int z) { return tree[x].sum + tree[y].sum - 2 * tree[z].sum; } inline int Get(int l, int r, int x, int y, int z, long long rem) { if (Num(x, y, z) <= 1) { return Sum(x, y, z) <= rem; } int m = (l + r) >> 1; if (rem <= Sum(tree[x].l, tree[y].l, tree[z].l)) { return Get(l, m, tree[x].l, tree[y].l, tree[z].l, rem); } rem -= Sum(tree[x].l, tree[y].l, tree[z].l); return Num(tree[x].l, tree[y].l, tree[z].l) + Get(m + 1, r, tree[x].r, tree[y].r, tree[z].r, rem); } } st; int n, m, q, a, b, c[100000], d[100000], gold, rem; int sp[20][100000], depth[100000], root[100000]; long long silver; vector<pair<int, int>> g[100000], p; vector<int> v[100000]; inline void DFS(int node, int par, int last = -1) { sp[0][node] = par; for (int i = 1; i < 20; ++i) { sp[i][node] = sp[i - 1][sp[i - 1][node]]; } root[node] = root[par]; if (last != -1) { for (auto &i : v[last]) { st.Update(root[node], 1, m, d[i], c[i]); } } // each node store a root of a segment tree that have the data of the road from 1 to node for (auto &i : g[node]) { if (i.first != par) { depth[i.first] = depth[node] + 1; DFS(i.first, node, i.second); } } } inline int LCA(int ina, int inb) { if (depth[ina] != depth[inb]) { if (depth[ina] < depth[inb]) { swap(ina, inb); } for (int i = 19; i >= 0; --i) { if (depth[sp[i][ina]] >= depth[inb]) { ina = sp[i][ina]; } } } if (ina == inb) { return ina; } for (int i = 19; i >= 0; --i) { if (sp[i][ina] != sp[i][inb]) { ina = sp[i][ina]; inb = sp[i][inb]; } } return sp[0][ina]; } int main() { setup(); cin >> n >> m >> q; for (int i = 0; i < n - 1; ++i) { cin >> a >> b; g[a - 1].push_back({b - 1, i}); g[b - 1].push_back({a - 1, i}); } for (int i = 0; i < m; ++i) { cin >> a >> c[i]; p.push_back({c[i], i}); v[a - 1].push_back(i); } sort(p.begin(), p.end()); for (int i = 0; i < p.size(); ++i) { d[p[i].second] = i + 1; } DFS(0, 0); while (q--) { cin >> a >> b >> gold >> silver; a--; b--; rem = st.Num(root[a], root[b], root[LCA(a, b)]) - st.Get(1, m, root[a], root[b], root[LCA(a, b)], silver); cout << max(-1, gold - rem) << "\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...