Submission #1046581

#TimeUsernameProblemLanguageResultExecution timeMemory
1046581TurkhuuTwo Currencies (JOI23_currencies)C++17
100 / 100
2220 ms149192 KiB
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int N, M, Q, timer;
vector<int> sz, pos, dep, par, top;
vector<vector<int>> adj;
struct S {
    S *l, *r; ll s;
    S() {l = r = nullptr; s = 0;}
    S(ll a) {l = r = nullptr; s = a;}
    S(S *x) : l(x->l), r(x->r), s(x->s) {}
    S(S *u, S *v) : l(u), r(v), s(0) {
        if (l) s += l->s;
        if (r) s += r->s;
    }
};
vector<S*> roots;
S* build(int l, int r) {
    if (l + 1 == r) return new S(0LL);
    int m = (l + r) / 2;
    return new S(build(l, m), build(m, r));
}
S* upd(S* i, int l, int r, int j, ll v) {
    if (l + 1 == r) return new S(i->s + v);
    int m = (l + r) / 2; return j < m
    ? new S(upd(i->l, l, m, j, v), i->r)
    : new S(i->l, upd(i->r, m, r, j, v));
}
ll qry(S* i, int l, int r, int L, int R) {
    if (R <= l || r <= L) return 0;
    if (L <= l && r <= R) return i->s;
    int m = (l + r) / 2;
    return qry(i->l, l, m, L, R) + qry(i->r, m, r, L, R);
}
void init(int x) {
    sz[x] = 1;
    for (auto &y : adj[x]) {
        adj[y].erase(find(adj[y].begin(), adj[y].end(), par[y] = x));
        dep[y] = dep[x] + 1;
        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);
    }
}
ll path(int x, int y, int z) {
    ll s = 0;
    for (; top[x] != top[y]; x = par[top[x]]) {
        if (dep[top[x]] < dep[top[y]]) swap(x, y);
        s += qry(roots[z], 0, N, pos[top[x]], pos[x] + 1);
    }
    if (dep[x] > dep[y]) swap(x, y);
    return s += qry(roots[z], 0, N, pos[x] + 1, pos[y] + 1);
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin >> N >> M >> Q;
    sz.resize(N);
    pos.resize(N);
    dep.resize(N);
    adj.resize(N);
    top.resize(N);
    par.resize(N, -1);
    vector<pair<int, int>> edges(N - 1);
    for (int i = 0; i < N - 1; i++) {
        int a, b;
        cin >> a >> b;
        a--, b--;
        edges[i] = {a, b};
        adj[a].push_back(i);
        adj[b].push_back(i);
    }
    vector<int> w(N - 1); {
        function<void(int, int)> dfs = [&](int x, int p) {
            for (auto &y : adj[x]) {
                int i = y;
                auto [u, v] = edges[y];
                y = x ^ u ^ v;
                if (y == p) continue;
                w[i] = y;
                dfs(y, x);
            }
        };
        dfs(0, -1);
    }
    init(0); dfs(0);
    roots.push_back(build(0, N));
    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());
    for (auto [s, i] : ch) {
        roots.push_back(upd(roots.back(), 0, N, pos[i], s));
    }
    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;
            path(S[i], T[i], mi) <= Y[i] ? lo = mi : hi = mi - 1;
        }
        a[lo].push_back(i);
    }
    roots.resize(1);
    for (int i = M; i >= 0; i--) {
        if (i < M) {
            auto [s, j] = ch[i];
            roots.push_back(upd(roots.back(), 0, N, pos[j], 1));
        }
        for (auto j : a[i]) {
            ans[j] = max<ll>(-1, X[j] - path(S[j], T[j], M - i));
        }
    }
    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...