Submission #916755

#TimeUsernameProblemLanguageResultExecution timeMemory
916755happypotatoTwo Currencies (JOI23_currencies)C++17
100 / 100
4979 ms120236 KiB
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair<int, int>
#define ff first
#define ss second
#define pb push_back
// global
// persistent segment tree (point add range sum)
struct Node {
    int val, cnt;
    Node *l, *r;
 
    Node() : val(0), cnt(0), l(nullptr), r(nullptr) {}
    Node(int x, int y) : val(x), cnt(y), l(nullptr), r(nullptr) {}
    Node(Node *ll, Node *rr) : val(ll->val + rr->val), cnt(ll->cnt + rr->cnt), l(ll), r(rr) {}
};
const int mxN = 1e5 + 1;
int n;
Node *segstore[mxN];
Node *SegBuild(int l = 1, int r = n) {
    if (l == r) {
        return new Node();
    }
    int mid = (l + r) >> 1;
    return new Node(SegBuild(l, mid), SegBuild(mid + 1, r));
}
Node *SegUpdate(Node *seg, int pos, int val, int l = 1, int r = n) {
    if (l == r) {
        return new Node(seg->val + val, seg->cnt + 1);
    }
    int mid = (l + r) >> 1;
    if (pos <= mid) {
        return new Node(SegUpdate(seg->l, pos, val, l, mid), seg->r);
    } else {
        return new Node(seg->l, SegUpdate(seg->r, pos, val, mid + 1, r));
    }
    return new Node();
}
pii SegQuery(Node *seg, int &tl, int &tr, int l = 1, int r = n) {
    if (tl <= l && r <= tr) {
        return {seg->val, seg->cnt};
    }
    int mid = (l + r) >> 1;
    pii res = {0, 0};
    pii ret;
    if (tl <= mid) {
        ret = SegQuery(seg->l, tl, tr, l, mid);
        res.ff += ret.ff; res.ss += ret.ss;
    }
    if (tr > mid) {
        ret = SegQuery(seg->r, tl, tr, mid + 1, r);
        res.ff += ret.ff; res.ss += ret.ss;
    }
    return res;
}
// hld
vector<int> adj[mxN];
int par[mxN], rr[mxN], sz[mxN];
int heavy[mxN]; // heavy edge for children
int root[mxN]; // root of heavy edges
int corr[mxN]; // euler tour to map to segtree
void HLDInit(int u = 1, int pp = 0) {
    par[u] = pp;
    rr[u] = rr[pp] + 1;
    sz[u] = 1;
    pii big = {-1, -1};
    for (int v : adj[u]) {
        if (v != pp) {
            HLDInit(v, u);
            sz[u] += sz[v];
            if (sz[v] > big.ff) big = {sz[v], v};
        }
    }
    heavy[u] = big.ss;
}
int segptr = 1;
void HLDProcess(int u = 1, int pp = 0, int high = 1) {
    root[u] = high;
    corr[u] = segptr++;
    if (heavy[u] == -1) return;
    HLDProcess(heavy[u], u, high);
    for (int v : adj[u]) {
        if (v != heavy[u] && v != pp) HLDProcess(v, u, v);
    }
}
int HLDLCA(int u, int v) {
    while (root[u] != root[v]) {
        if (rr[root[u]] > rr[root[v]]) swap(u, v);
        v = par[root[v]];
    }
    return (rr[u] < rr[v] ? u : v);
}
void HLDUpdate(int &ver, int u, int v, int &val) {
    // depth[u] < depth[v], update v
    if (rr[u] > rr[v]) swap(u, v);
    // cerr << "HLDUPDATE " << u << ' ' << v << endl;
    segstore[ver] = SegUpdate(segstore[ver - 1], corr[v], val);
}
pii HLDQueryAnces(int &ver, int u, int v) {
    int ptr1, ptr2;
    pii res = {0, 0};
    pii ret;
    while (root[u] != root[v]) {
        ptr1 = corr[u]; ptr2 = corr[root[u]];
        if (ptr1 > ptr2) swap(ptr1, ptr2);
        ret = SegQuery(segstore[ver], ptr1, ptr2);
        res.ff += ret.ff; res.ss += ret.ss;
        u = par[root[u]];
    }
    if (rr[u] > rr[v]) swap(u, v);
    if (u != v) {
        ptr1 = corr[heavy[u]]; ptr2 = corr[v];
        if (ptr1 > ptr2) swap(ptr1, ptr2);
        ret = SegQuery(segstore[ver], ptr1, ptr2);
        res.ff += ret.ff; res.ss += ret.ss;
    }
    return res;
}
pii HLDQuery(int &ver, int u, int v) {
    int lca = HLDLCA(u, v);
    pii lhs = HLDQueryAnces(ver, u, lca);
    pii rhs = HLDQueryAnces(ver, v, lca);
    // cerr << "HLDQUERY\n";
    // cerr << ver << ' ' << u << ' ' << v << ' ' << lca << endl;
    // cerr << lhs.ff << ' ' << lhs.ss << endl;
    // cerr << rhs.ff << ' ' << rhs.ss << endl;
    return {lhs.ff + rhs.ff, lhs.ss + rhs.ss};
}
void init() {
    // init
 
}
void solve() {
    // solve
    int m, q;
    cin >> n >> m >> q;
    pii edges[n];
    for (int i = 1; i <= n - 1; i++) {
        int u, v;
        cin >> u >> v;
        adj[u].pb(v);
        adj[v].pb(u);
        edges[i] = {u, v};
    }
 
    HLDInit();
    HLDProcess();
    pii updates[m + 1];
    for (int i = 1; i <= m; i++) {
        cin >> updates[i].ff >> updates[i].ss;
    }
    sort(updates + 1, updates + m + 1, [&](pii &lhs, pii &rhs) { return lhs.ss < rhs.ss; });
    
    segstore[0] = SegBuild();
    for (int i = 1; i <= m; i++) {
        HLDUpdate(i, edges[updates[i].ff].ff, edges[updates[i].ff].ss, updates[i].ss);
    }
 
    while (q--) {
        int s, t, x, y;
        cin >> s >> t >> x >> y;
        int lb = 0, rb = m;
        pii ret;
        while (lb < rb) {
            int mid = (lb + rb + 1) >> 1;
            ret = HLDQuery(mid, s, t);
            if (ret.ff <= y) {
                lb = mid;
            } else {
                rb = mid - 1;
            }
        }
        ret = HLDQuery(lb, s, t);
        // cerr << lb << ' ' << ret.ff << ' ' << ret.ss << endl;
        // cerr << HLDQuery(m, s, t).ff << ' ' << HLDQuery(m, s, t).ss << endl;
        x -= HLDQuery(m, s, t).ss - HLDQuery(lb, s, t).ss;
        cout << (x < 0 ? -1 : x) << '\n';
    }
}
int32_t main() {
    ios::sync_with_stdio(0); cin.tie(0);
    init(); solve();
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...