#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
const int LOG = 17;
struct Edge { int to, id; };
int N, M, Q;
vector<Edge> g[MAXN];
vector<vector<int>> edgeChk; // edgeChk[i] = checkpoint list of edge i
int depth[MAXN], parent[MAXN][LOG];
long long sumSilver[MAXN][LOG];
int edgeToParent[MAXN]; // edge id connecting v -> parent[v][0]
void dfs(int u, int p, int peid) {
edgeToParent[u] = peid;
for (auto &e : g[u]) {
int v = e.to, eid = e.id;
if (v == p) continue;
depth[v] = depth[u] + 1;
parent[v][0] = u;
sumSilver[v][0] = 0;
for (int c : edgeChk[eid])
sumSilver[v][0] += c;
dfs(v, u, eid);
}
}
void build() {
depth[1] = 0;
parent[1][0] = 1;
sumSilver[1][0] = 0;
edgeToParent[1] = -1; // root has no incoming edge
dfs(1, 0, -1);
for (int k = 1; k < LOG; ++k) {
for (int v = 1; v <= N; ++v) {
int mid = parent[v][k-1];
parent[v][k] = parent[mid][k-1];
sumSilver[v][k] = sumSilver[v][k-1] + sumSilver[mid][k-1];
}
}
}
pair<long long, vector<int>> climb(int u, int dist) {
long long tot = 0;
vector<int> collected;
for (int k = LOG - 1; k >= 0; --k) {
if ((1 << k) <= dist) {
tot += sumSilver[u][k];
// get checkpoints from u up to parent[u][k]
int curr = u;
for (int i = 0; i < (1 << k); ++i) {
int eid = edgeToParent[curr];
if (eid != -1) {
for (int c : edgeChk[eid]) collected.push_back(c);
}
curr = parent[curr][0];
}
u = curr;
dist -= (1 << k);
}
}
return {tot, collected};
}
int lca(int u, int v) {
if (depth[u] < depth[v]) swap(u, v);
int diff = depth[u] - depth[v];
for (int k = 0; k < LOG; ++k)
if (diff & (1 << k)) u = parent[u][k];
if (u == v) return u;
for (int k = LOG - 1; k >= 0; --k) {
if (parent[u][k] != parent[v][k]) {
u = parent[u][k];
v = parent[v][k];
}
}
return parent[u][0];
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> N >> M >> Q;
vector<pair<int,int>> edges(N-1);
for (int i = 0; i < N-1; ++i) {
int a, b;
cin >> a >> b;
edges[i] = {a, b};
g[a].push_back({b, i});
g[b].push_back({a, i});
}
edgeChk.assign(N-1, {});
for (int i = 0; i < M; ++i) {
int p;
long long c;
cin >> p >> c;
edgeChk[p-1].push_back((int)c);
}
build();
while (Q--) {
int s, t;
long long X, Y;
cin >> s >> t >> X >> Y;
int anc = lca(s, t);
auto [s1, c1] = climb(s, depth[s] - depth[anc]);
auto [s2, c2] = climb(t, depth[t] - depth[anc]);
long long totalSilver = s1 + s2;
vector<int> all = c1;
all.insert(all.end(), c2.begin(), c2.end());
if (totalSilver <= Y) {
cout << X << '\n';
continue;
}
int need = totalSilver - Y;
if ((int)all.size() > X) {
nth_element(all.begin(), all.begin() + X, all.end(), greater<int>());
all.resize(X);
}
sort(all.begin(), all.end(), greater<int>());
int usedGold = 0;
for (int c : all) {
if (totalSilver <= Y) break;
totalSilver -= c;
usedGold++;
}
if (totalSilver <= Y && usedGold <= X)
cout << (X - usedGold) << '\n';
else
cout << -1 << '\n';
}
return 0;
}
# | 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... |