Submission #1126034

#TimeUsernameProblemLanguageResultExecution timeMemory
1126034TurkhuuTwo Currencies (JOI23_currencies)C++20
100 / 100
2694 ms161416 KiB
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
struct HLD {
    bool e; int n, timer; vector<vector<int>> adj;
    vector<int> sz, dep, top, pos, par;
    HLD(int n, bool edge = 0) : e(edge), n(n), timer(0), 
    adj(n), sz(n), dep(n), top(n), pos(n), par(n, -1) {}
    void add_edge(int x, int y) {
        adj[x].push_back(y);
        adj[y].push_back(x);
    }
    void init(int x) {
        sz[x] = 1;
        for (auto &y : adj[x]) {
            dep[y] = dep[x] + 1;
            adj[y].erase(find(adj[y].begin(), adj[y].end(), par[y] = x));
            init(y);
            sz[x] += sz[y];
            if (sz[y] > sz[adj[x][0]]) swap(y, adj[x][0]);
        }
    }
    void dfs(int x) {
        pos[x] = timer++;
        for (auto y : adj[x]) {
            top[y] = y == adj[x][0] ? top[x] : y;
            dfs(y);
        }
    }
    void build(int r = 0) {
        par[r] = -1;
        top[r] = r;
        dep[r] = 0;
        init(r);
        dfs(r);
    }
    int lca(int x, int y) {
        for (; top[x] != top[y]; x = par[top[x]]) {
            if (dep[top[x]] < dep[top[y]]) swap(x, y);
        }
        return dep[x] < dep[y] ? x : y;
    }
    template<class F> int trav_path(int x, int y, F f) {
        for (; top[x] != top[y]; x = par[top[x]]) {
            if (dep[top[x]] < dep[top[y]]) swap(x, y);
            f(pos[top[x]], pos[x] + 1);
        }
        if (dep[x] > dep[y]) swap(x, y);
        f(pos[x] + e, pos[y] + 1);
        return x;
    }
    int operator[](int i) {return pos[i];}
};
template<class S, S (*f)(S, S), S e> struct PST {
    struct T {
        T *l, *r; S s;
        T() : s(e) {l = r = nullptr;}
        T(const S &v) : s(v) {l = r = nullptr;}
        T(T *t) : l(t->l), r(t->r), s(t->s) {}
        T(T *a, T *b) : l(a), r(b), s(e) {
            if (l) s = f(s, l->s);
            if (r) s = f(s, r->s);
        }
    };
    int n; vector<T*> root;
    PST(int m) : PST(vector<S>(m, e)) {}
    PST(const vector<S> &a) : n(a.size()) {
        function<T*(int, int)> build = [&](int l, int r) {
            if (l + 1 == r) return new T(a[l]);
            int m = (l + r) / 2;
            return new T(build(l, m), build(m, r));
        };
        root.push_back(build(0, n));
    }
    T* upd(T *i, int l, int r, int j, const S &v, bool set) {
        if (l + 1 == r) return new T(set ? v : f(i->s, v));
        int m = (l + r) / 2; return j < m
        ? new T(upd(i->l, l, m, j, v, set), i->r)
        : new T(i->l, upd(i->r, m, r, j, v, set));
    }
    S qry(T *i, int l, int r, int L, int R) {
        if (R <= l || r <= L) return e;
        if (L <= l && r <= R) return i->s;
        int m = (l + r) / 2;
        return f(qry(i->l, l, m, L, R), qry(i->r, m, r, L, R));
    }
    int last() {
        return root.size() - 1;
    }
    int copy(int k) {
        root.push_back(new T(root[k]));
        return root.size() - 1;
    }
    void upd(int k, int i, const S &v, bool set = 1) {
        root[k] = upd(root[k], 0, n, i, v, set);
    }
    S qry(int k, int l, int r) {
        return qry(root[k], 0, n, l, r);
    }
};
ll f(ll a, ll b) {return a + b;}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int N, M, Q;
    cin >> N >> M >> Q;
    HLD hld(N, 1);
    vector<pair<int, int>> edges(N - 1);
    vector<vector<pair<int, int>>> adj(N);
    for (int i = 0; i < N - 1; i++) {
        int a, b;
        cin >> a >> b;
        a--, b--;
        edges[i] = {a, b};
        adj[a].emplace_back(b, i);
        adj[b].emplace_back(a, i);
        hld.add_edge(a, b);
    }
    vector<int> w(N - 1); {
        function<void(int, int)> dfs = [&](int x, int p) {
            for (auto [y, z] : adj[x]) {
                if (y == p) continue;
                w[z] = y;
                dfs(y, x);
            }
        };
        dfs(0, -1);
    }
    hld.build();
    vector<pair<int, int>> ch(M);
    for (int i = 0; i < M; i++) {
        int e, s;
        cin >> e >> s; e--;
        ch[i] = {s, w[e]};
    }
    sort(ch.begin(), ch.end());
    PST<ll, f, 0> pst(N);
    for (auto [s, i] : ch) {
        pst.upd(pst.copy(pst.last()), hld.pos[i], s, 0);
    }
    vector<vector<int>> a(M + 1);
    vector<int> S(Q), T(Q), X(Q), ans(Q);
    vector<ll> Y(Q);
    for (int i = 0; i < Q; i++) {
        cin >> S[i] >> T[i] >> X[i] >> Y[i];
        S[i]--, T[i]--;
        int lo = 0, hi = M;
        while (lo < hi) {
            int mi = (lo + hi + 1) / 2;
            ll s = 0;
            hld.trav_path(S[i], T[i], [&](int l, int r) {
                s += pst.qry(mi, l, r);
            }); 
            s <= Y[i] ? lo = mi : hi = mi - 1;
        }
        a[lo].push_back(i);
    }
    pst = PST<ll, f, 0>(N);
    for (int i = M; i >= 0; i--) {
        if (i < M) {
            auto [s, j] = ch[i];
            pst.upd(pst.copy(pst.last()), hld.pos[j], 1, 0);
        }
        for (auto j : a[i]) {
            int cnt = 0;
            hld.trav_path(S[j], T[j], [&](int l, int r) {
                cnt += pst.qry(pst.last(), l, r);
            });
            ans[j] = max<ll>(-1, X[j] - cnt);
        }
    }
    for (int i = 0; i < Q; i++) cout << ans[i] << "\n";
    return 6/22;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...