#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100000 + 5;
const int LOG = 17;
// Cấu trúc cạnh
struct Edge { int to, id; };
// Persistent SegTree node
struct PST {
    PST *l, *r;
    int cnt;
    long long sum;
    PST(int _cnt=0, long long _sum=0, PST* _l=nullptr, PST* _r=nullptr)
      : l(_l), r(_r), cnt(_cnt), sum(_sum) {}
};
PST *nullNode = new PST();
// Cập nhật PST (thêm deltaCnt checkpoint có giá trị = val tại vị trí pos)
PST* update(PST* prev, int L, int R, int pos, int deltaCnt, int val) {
    if (pos < L || pos > R) return prev;
    if (L == R) {
        return new PST(prev->cnt + deltaCnt,
                       prev->sum + 1LL * deltaCnt * val,
                       nullNode, nullNode);
    }
    int M = (L + R) >> 1;
    PST *left = prev->l, *right = prev->r;
    if (pos <= M)
        left = update(prev->l,   L, M, pos, deltaCnt, val);
    else
        right = update(prev->r, M+1, R, pos, deltaCnt, val);
    return new PST(left->cnt + right->cnt,
                   left->sum + right->sum,
                   left, right);
}
// Truy vấn tổng sum trên đoạn [lq..rq]
long long querySum(PST* U, PST* V, PST* A, PST* B,
                   int L, int R, int lq, int rq) {
    if (rq < L || R < lq) return 0;
    if (lq <= L && R <= rq) {
        return U->sum + V->sum - A->sum - B->sum;
    }
    int M = (L + R) >> 1;
    return querySum(U->l, V->l, A->l, B->l, L, M, lq, rq)
         + querySum(U->r, V->r, A->r, B->r, M+1, R, lq, rq);
}
// Truy vấn cnt trên đoạn [lq..rq]
int queryCnt(PST* U, PST* V, PST* A, PST* B,
             int L, int R, int lq, int rq) {
    if (rq < L || R < lq) return 0;
    if (lq <= L && R <= rq) {
        return U->cnt + V->cnt - A->cnt - B->cnt;
    }
    int M = (L + R) >> 1;
    return queryCnt(U->l, V->l, A->l, B->l, L, M, lq, rq)
         + queryCnt(U->r, V->r, A->r, B->r, M+1, R, lq, rq);
}
// Tìm số checkpoint lớn nhất (bắt đầu từ giá trị cao) cần dùng để đạt tổng ≥ need
int getMinUsed(PST* U, PST* V, PST* A, PST* B,
               int L, int R, long long need,
               const vector<int>& allVals) {
    if (need <= 0) return 0;
    if (L == R) {
        long long val = allVals[L];
        // đảm bảo val > 0 (theo đề bài, checkpoint luôn > 0)
        return int((need + val - 1) / val);
    }
    int M = (L + R) >> 1;
    // tổng của nửa phải (giá trị lớn hơn)
    long long sumR = querySum(U->r, V->r, A->r, B->r, M+1, R, M+1, R);
    int cntR   = queryCnt(U->r, V->r, A->r, B->r, M+1, R, M+1, R);
    if (sumR >= need) {
        return getMinUsed(U->r, V->r, A->r, B->r, M+1, R, need, allVals);
    } else {
        return cntR + getMinUsed(U->l, V->l, A->l, B->l, L, M, need - sumR, allVals);
    }
}
int N, M, Q;
vector<Edge> g[MAXN];
vector<int> edgeChk[MAXN];
int depthArr[MAXN], parentArr[MAXN][LOG];
PST* root[MAXN];
vector<int> allVals;
// Xây dựng root[v] và parentArr[v][0] qua DFS
void dfs(int u, int p) {
    for (auto &e : g[u]) {
        int v = e.to, eid = e.id;
        if (v == p) continue;
        depthArr[v] = depthArr[u] + 1;
        parentArr[v][0] = u;
        // kế thừa PST của u
        PST* curr = root[u];
        // thêm các checkpoint của cạnh (u->v)
        for (int c : edgeChk[eid]) {
            int pos = int(lower_bound(allVals.begin(), allVals.end(), c) - allVals.begin());
            curr = update(curr, 0, (int)allVals.size() - 1, pos, 1, c);
        }
        root[v] = curr;
        dfs(v, u);
    }
}
// Tìm LCA
int lca(int u, int v) {
    if (depthArr[u] < depthArr[v]) swap(u, v);
    int diff = depthArr[u] - depthArr[v];
    for (int k = 0; k < LOG; ++k)
        if (diff >> k & 1) u = parentArr[u][k];
    if (u == v) return u;
    for (int k = LOG - 1; k >= 0; --k) {
        if (parentArr[u][k] != parentArr[v][k]) {
            u = parentArr[u][k];
            v = parentArr[v][k];
        }
    }
    return parentArr[u][0];
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin >> N >> M >> Q;
    // đọc cây
    for (int i = 0; i < N - 1; ++i) {
        int a, b;
        cin >> a >> b;
        g[a].push_back({b, i});
        g[b].push_back({a, i});
    }
    // đọc checkpoint
    for (int i = 0; i < M; ++i) {
        int p, c;
        cin >> p >> c;
        edgeChk[p-1].push_back(c);
        allVals.push_back(c);
    }
    // nén giá trị
    sort(allVals.begin(), allVals.end());
    allVals.erase(unique(allVals.begin(), allVals.end()), allVals.end());
    // khởi tạo nullNode
    nullNode->l = nullNode->r = nullNode;
    nullNode->cnt = nullNode->sum = 0;
    // gốc PST tại node 1
    root[1] = nullNode;
    depthArr[1] = 0;
    parentArr[1][0] = 1;
    // DFS để build PST và parentArr[][0]
    dfs(1, 0);
    // build parentArr cho binary lifting
    for (int k = 1; k < LOG; ++k) {
        for (int v = 1; v <= N; ++v) {
            parentArr[v][k] = parentArr[ parentArr[v][k-1] ][k-1];
        }
    }
    // xử lý truy vấn
    while (Q--) {
        int s, t;
        long long X, Y;
        cin >> s >> t >> X >> Y;
        int c = lca(s, t);
        // tính tổng silver trên đường s->t
        long long sumS = root[s]->sum + root[t]->sum
                       - 2LL * root[c]->sum;
        if (sumS <= Y) {
            cout << X << "\n";
            continue;
        }
        long long need = sumS - Y;
        // tìm số checkpoint cần dùng
        // B = root[parentArr[c][0]] (nếu c==1 thì parentArr[1][0]=1 => root[1]=nullNode)
        PST* nodeA = root[c];
        PST* nodeB = root[ parentArr[c][0] ];
        int used = getMinUsed(root[s], root[t], nodeA, nodeB,
                              0, (int)allVals.size() - 1,
                              need, allVals);
        if (used <= X) cout << (X - used) << "\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... |