Submission #1165527

#TimeUsernameProblemLanguageResultExecution timeMemory
1165527trvhungTwo Currencies (JOI23_currencies)C++20
100 / 100
1212 ms33644 KiB
#include <bits/stdc++.h>
// #include <ext/rope>
// #include <ext/pb_ds/assoc_container.hpp>

// using namespace __gnu_pbds;
// using namespace __gnu_cxx;
using namespace std;

// #pragma GCC optimize("O3,unroll-loops")
// #pragma GCC target("avx2,bmi,bmi2,popcnt,lzcnt")

// #define   ordered_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>
#define            ll long long
#define           ull unsigned long long
#define            ld long double
#define            pb push_back
#define  bit(mask, i) ((mask >> i) & 1)
#define            el '\n'
#define             F first
#define             S second

template <class X, class Y> bool maximize(X &x, const Y &y) { return (x < y ? x = y, 1 : 0); }
template <class X, class Y> bool minimize(X &x, const Y &y) { return (x > y ? x = y, 1 : 0); }

const int INF = 1e9;
const ll LINF = 1e18;
const int MOD = 1e9 + 7;
const int MULTI = 0;
const ld eps = 1e-9;
const int dx[4] = {0, 1, 0, -1}, dy[4] = {1, 0, -1, 0}; // R D L U
const int ddx[4] = {-1, 1, 1, -1}, ddy[4] = {1, 1, -1, -1}; // UR DR DL UL
const char cx[4] = {'R', 'D', 'L', 'U'};
const ll base = 31;
const int nMOD = 2;
const ll mods[] = {(ll)1e9 + 10777, (ll)1e9 + 19777, (ll)1e9 + 3, (ll)1e9 + 3777};

const int maxn = 1e5 + 5;
int n, m, q, cnt[maxn], l[maxn], r[maxn], A[maxn], B[maxn], L[maxn], S[maxn], T[maxn], X[maxn], curChain, curPos, sz[maxn], chainID[maxn], pos[maxn], chainHead[maxn], h[maxn], par[maxn];
vector<int> adj[maxn], queries[maxn];
ll Y[maxn];
pair<int, int> P[maxn];

void dfs(int u) {
    sz[u] = 1;
    for (int v: adj[u])
        if (v != par[u]) {
            par[v] = u;
            h[v] = h[u] + 1;
            dfs(v);
            sz[u] += sz[v];
        }
}

void hld(int u) {
    if (!chainHead[curChain]) chainHead[curChain] = u;
    chainID[u] = curChain; pos[u] = curPos++;

    int nxt = 0;
    for (int v: adj[u])
        if (v != par[u] && sz[v] > sz[nxt])
            nxt = v;

    if (nxt) hld(nxt);
    for (int v: adj[u])
        if (v != par[u] && v != nxt) {
            curChain++;
            hld(v);
        }
}

int LCA(int u, int v) {
    while (chainID[u] != chainID[v])
        if (chainID[u] > chainID[v])
            u = par[chainHead[chainID[u]]];
        else 
            v = par[chainHead[chainID[v]]];

    return h[u] < h[v] ? u : v;
}

struct BIT {
    ll bit[maxn];

    void init() {
        fill(bit + 1, bit + 1 + n, 0);
    }   

    void update(int id, int v) {
        for (; id <= n; id += id & -id)
            bit[id] += v;
    }

    ll get(int id) {
        ll res = 0;
        for (; id > 0; id -= id & -id)
            res += bit[id];
        return res;
    }

    ll getRange(int l, int r) {
        return l > r ? 0 : get(r) - get(l - 1);
    }
} BIT[2];

void update(int u, int v, int id, int val) {
    if (pos[u] < pos[v]) swap(u, v);
    BIT[id].update(pos[u], val);
}

ll get(int u, int v, int id) {
    int lca = LCA(u, v);
    ll res = 0;

    while (chainID[u] != chainID[lca]) {
        res += BIT[id].getRange(pos[chainHead[chainID[u]]], pos[u]);
        u = par[chainHead[chainID[u]]];
    }

    while (chainID[v] != chainID[lca]) {
        res += BIT[id].getRange(pos[chainHead[chainID[v]]], pos[v]);
        v = par[chainHead[chainID[v]]];
    }

    if (pos[u] > pos[v]) swap(u, v);
    res += BIT[id].getRange(pos[u] + 1, pos[v]);

    return res;
}

void solve() {
    cin >> n >> m >> q;
    for (int i = 1; i < n; ++i) {
        cin >> A[i] >> B[i];
        adj[A[i]].push_back(B[i]);
        adj[B[i]].push_back(A[i]);
    }

    curChain = curPos = 1;
    dfs(1); hld(1);

    for (int i = 1; i <= m; ++i) 
        cin >> P[i].S >> P[i].F;

    for (int i = 1; i <= q; ++i) {
        cin >> S[i] >> T[i] >> X[i] >> Y[i];
        L[i] = LCA(S[i], T[i]);
        l[i] = 0; r[i] = m;
    }

    sort(P + 1, P + 1 + m);

    while (true) {
        for (int i = 0; i <= m; ++i)
            queries[i].clear();

        bool all_answered = true;
        for (int i = 1; i <= q; ++i) {
            if (l[i] > r[i]) continue;
            all_answered = false;
            queries[(l[i] + r[i]) >> 1].push_back(i);
        }

        if (all_answered) break;

        BIT[0].init(); BIT[1].init();
        for (int i = 1; i <= m; ++i) {
            int u = A[P[i].S], v = B[P[i].S];
            update(u, v, 0, 1);
        }

        for (int i = 0; i <= m; ++i) {
            for (int j: queries[i]) {
                ll s = get(S[j], T[j], 1);
                if (s <= Y[j]) {
                    cnt[j] = get(S[j], T[j], 0);
                    l[j] = i + 1;
                } else
                    r[j] = i - 1;
            }
            if (i < m) {
                int val = P[i + 1].F;
                int u = A[P[i + 1].S], v = B[P[i + 1].S];
                update(u, v, 0, -1);
                update(u, v, 1, val);
            }
        }
    }
    
    for (int i = 1; i <= q; ++i)
        cout << max(X[i] - cnt[i], -1) << el;
}

signed main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);

    if (!MULTI) solve();
    else {
        int test; cin >> test;
        while (test--) solve();
    }
    
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...