This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> pl;
typedef pair<int,int> pii;
typedef tuple<int,int,int> tt;
#define all(a) a.begin(), a.end()
#define filter(a) a.erase(unique(all(a)), a.end())
const int mn = 1e5 + 5;
struct BIT {
vector<ll> tr;
BIT (int sz = 0) : tr(sz + 1) {}
int p (int k) { return k & -k; }
void update (int k, ll val) {
//cerr << "update id " << k << "\n";
for (; k < tr.size(); k += p(k)) tr[k] += val;
}
ll preSum (int k, ll ans = 0) {
//cerr << "query id " << k << "\n";
for (k; k; k -= p(k)) ans += tr[k];
return ans;
}
ll query (int l, int r) { return preSum(r) - preSum(l - 1); }
};
int up[mn][18], depth[mn], sz[mn], chain[mn], szc[mn];
vector<BIT> treeSum(mn), treeCnt(mn);
pii edge[mn], cpt[mn];
vector<int> adj[mn];
/* tree DFS functions */
int preDfs (int u, int p, int d) {
up[u][0] = p, depth[u] = d, sz[u] = 1;
for (int i = 1; i < 18; i++)
up[u][i] = up[up[u][i - 1]][i - 1];
for (int v : adj[u])
if (v != p) sz[u] += preDfs(v, u, d + 1);
return sz[u];
}
bool compare (int a, int b) {
return sz[a] > sz[b];
}
void hldDfs (int u, int p, bool toParent) {
chain[u] = (toParent ? chain[p] : u), szc[chain[u]]++;
sort(all(adj[u]), compare);
bool flg = 1;
for (int v : adj[u]) {
if (v == p) continue;
hldDfs(v, u, flg);
flg = 0;
}
}
/* LCA functions */
int goUp (int a, int k) {
for (int i = 0; i < 18; i++)
if (k & (1 << i)) a = up[a][i];
return a;
}
int lca (int a, int b) {
if (depth[a] < depth[b]) swap(a, b);
a = goUp(a, depth[a] - depth[b]);
if (a == b) return a;
for (int i = 17; i >= 0; i--)
if (up[a][i] != up[b][i]) a = up[a][i], b = up[b][i];
return up[a][0];
}
/* HLD update & query functions */
int getID (int u) { return depth[u] - depth[chain[u]] + 1; }
ll getHLD (int u, int p, vector<BIT> &tree) {
ll ans = 0;
while (chain[u] != chain[p]) {
ans += tree[chain[u]].preSum(getID(u));
u = up[chain[u]][0];
}
return ans + tree[chain[u]].query(getID(p), getID(u));
}
void updateHLD (int u, ll delta, vector<BIT> &tree) {
tree[chain[u]].update(getID(u), delta);
}
ll query (int u, int v, vector<BIT> &tree) {
int lc = lca(u, v); ll ans = 0;
if (u != lc) ans += getHLD(u, goUp(u, depth[u] - depth[lc] - 1), tree);
if (v != lc) ans += getHLD(v, goUp(v, depth[v] - depth[lc] - 1), tree);
return ans;
}
void update (int k, int add) {
int c, id, u, v; tie(c, id) = cpt[k], tie(u, v) = edge[id];
int node = (depth[u] > depth[v] ? u : v);
updateHLD(node, c * add, treeSum);
updateHLD(node, -add, treeCnt);
}
ll gold[mn], silver[mn], ans[mn], stateHLD;
void solve (vector<tt> qr, int l, int r) {
int mid = ((l + r) >> 1) + 1;
while (stateHLD < mid) update(++stateHLD, 1);
while (stateHLD > mid) update(stateHLD--, -1);
if (l == r) {
// pay silver for only the first l checkpoints
update(stateHLD--, -1);
for (tt item : qr) {
int u, v, id; tie(u, v, id) = item;
ans[id] = query(u, v, treeCnt);
}
return;
}
vector<tt> toL, toR;
for (tt item : qr) {
int u, v, id; tie(u, v, id) = item;
if (query(u, v, treeSum) <= silver[id]) toR.push_back(item);
else toL.push_back(item);
}
if (toL.size()) solve(toL, l, mid - 1);
if (toR.size()) solve(toR, mid, r);
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
// read edges and setup HLD
int n, m, q; cin >> n >> m >> q;
for (int i = 1; i < n; i++) {
int a, b; cin >> a >> b;
adj[a].push_back(b);
adj[b].push_back(a);
edge[i] = {a, b};
}
preDfs(1, 1, 1);
hldDfs(1, 1, 0);
// setup BITs
for (int i = 1; i <= n; i++) {
if (!szc[i]) continue;
treeSum[i] = treeCnt[i] = BIT(szc[i]);
}
for (int i = 1; i <= m; i++) {
int p, c; cin >> p >> c;
int u, v; tie(u, v) = edge[p];
int node = (depth[u] > depth[v] ? u : v);
updateHLD(node, 1, treeCnt);
cpt[i] = {c, p};
}
sort(cpt + 1, cpt + 1 + m);
// read queries and setup PBS
vector<tt> qr(q);
for (int i = 0; i < q; i++) {
int u, v; cin >> u >> v >> gold[i] >> silver[i];
qr[i] = make_tuple(u, v, i);
}
solve(qr, 0, m);
// print final answers
for (int i = 0; i < q; i++) {
if (gold[i] < ans[i]) cout << -1 << "\n";
else cout << gold[i] - ans[i] << "\n";
}
return 0;
}
Compilation message (stderr)
currencies.cpp: In member function 'void BIT::update(int, ll)':
currencies.cpp:23:18: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<long long int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
23 | for (; k < tr.size(); k += p(k)) tr[k] += val;
| ~~^~~~~~~~~~~
currencies.cpp: In member function 'll BIT::preSum(int, ll)':
currencies.cpp:28:14: warning: statement has no effect [-Wunused-value]
28 | for (k; k; k -= p(k)) ans += tr[k];
| ^
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |