#include <bits/stdc++.h>
using namespace std;
const int N = 100'000 + 10;
int n, m, q;
pair<int, int> edge[N];
struct CP {
int p, c;
friend istream& operator >> (istream& is, CP& rhs) {
return is >> rhs.p >> rhs.c;
}
} cp[N];
struct Query {
int s, t, x, y;
friend istream& operator >> (istream& is, Query& rhs) {
return is >> rhs.s >> rhs.t >> rhs.x >> rhs.y;
}
} query[N];
vector<int> ad[N];
int f[N][17];
int st[N], ed[N], num;
void dfs(int u, int p = -1) {
st[u] = ++num;
for (int i = 1; i <= 16; ++i) f[u][i] = f[f[u][i - 1]][i - 1];
for (const auto& v : ad[u]) {
if (v == p) continue;
f[v][0] = u;
dfs(v, u);
}
ed[u] = num;
}
inline bool anc(int u, int v) { return st[u] <= st[v] && ed[u] >= ed[v]; }
int lca(int u, int v) {
if (anc(u, v)) return u;
if (anc(v, u)) return v;
for (int i = 16; i >= 0; --i)
if (!anc(f[u][i], v)) u = f[u][i];
return f[u][0];
}
vector<int> allC;
vector<int> save[N];
struct BIT {
long long bit[N];
void upd(int i, int x) {
for (; i <= n; i += i & -i) bit[i] += x;
}
int que(int i) {
long long ret = 0;
for (; i; i -= i & -i) ret += bit[i];
return ret;
}
void upd(int l, int r, int x) {
upd(l, x);
upd(r + 1, -x);
}
} T, D, F, Total;
int answer[N];
void dnc(int l, int r, vector<int>& Qlist) {
if (!Qlist.size()) return;
int mid = (l + r) >> 1;
for (int i = l; i <= mid; ++i) {
for (const auto& idx : save[i]) {
const auto& [u, v] = edge[idx];
T.upd(st[v], ed[v], allC[i]);
F.upd(st[v], ed[v], 1);
if (i == mid) D.upd(st[v], ed[v], 1);
}
}
array<vector<int>, 2> nxt;
for (const auto& idx : Qlist) {
auto [s, t, x, y] = query[idx];
int LCA = lca(s, t);
int total = T.que(st[s]) + T.que(st[t]) - 2 * T.que(st[LCA]),
cnt = D.que(st[s]) + D.que(st[t]) - 2 * D.que(st[LCA]),
useCnt = F.que(st[s]) + F.que(st[t]) - 2 * F.que(st[LCA]),
totalCnt = Total.que(st[s]) + Total.que(st[t]) - 2 * Total.que(st[LCA]);
total -= 1ll * allC[mid] * cnt;
useCnt -= cnt;
if (y < total) {
nxt[0].push_back(idx);
continue;
}
y -= total;
int cntAdd = y / allC[mid];
useCnt += min(cnt, cntAdd);
if (x < totalCnt - useCnt) {
nxt[1].push_back(idx);
continue;
}
nxt[1].push_back(idx);
answer[idx] = x - (totalCnt - useCnt);
}
for (const auto& idx : save[mid]) {
const auto& [u, v] = edge[idx];
D.upd(st[v], ed[v], -1);
}
if (l != r) dnc(mid + 1, r, nxt[1]);
for (int i = l; i <= mid; ++i) {
for (const auto& idx : save[i]) {
const auto& [u, v] = edge[idx];
T.upd(st[v], ed[v], -allC[i]);
F.upd(st[v], ed[v], -1);
}
}
if (l != r) dnc(l, mid, nxt[0]);
}
int32_t main() {
cin.tie(0)->sync_with_stdio(0);
cin >> n >> m >> q;
for (int i = 1; i < n; ++i) cin >> edge[i].first >> edge[i].second;
for (int i = 1; i <= m; ++i) cin >> cp[i];
for (int i = 1; i <= q; ++i) cin >> query[i];
for (int i = 1; i < n; ++i) {
const auto& [u, v] = edge[i];
ad[u].push_back(v);
ad[v].push_back(u);
}
dfs(f[1][0] = 1);
for (int i = 1; i < n; ++i) {
auto& [u, v] = edge[i];
if (anc(v, u)) swap(u, v);
}
{ // discrete
for (int i = 1; i <= m; ++i) allC.push_back(cp[i].c);
sort(allC.begin(), allC.end());
allC.erase(unique(allC.begin(), allC.end()), allC.end());
for (int i = 1; i <= m; ++i) {
auto it = upper_bound(allC.begin(), allC.end(), cp[i].c) - allC.begin();
save[it].push_back(cp[i].p);
}
allC.insert(allC.begin(), 0);
}
for (int i = 1; i <= m; ++i) {
const auto& [p, c] = cp[i];
int v = edge[p].second;
Total.upd(st[v], ed[v], 1);
}
fill(answer + 1, answer + q + 1, -1);
vector<int> Qlist(q); iota(Qlist.begin(), Qlist.end(), 1);
dnc(1, allC.size() - 1, Qlist);
for (int i = 1; i <= q; ++i) cout << answer[i] << "\n";
}
# | 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... |