Submission #1312326

#TimeUsernameProblemLanguageResultExecution timeMemory
13123261otaTwo Currencies (JOI23_currencies)C++20
100 / 100
2536 ms215120 KiB
#include <bits/stdc++.h>
using namespace std;
 
#define endl "\n"
#define int long long
#define pii pair<int, int>
#define ff first
#define ss second
#define entire(x) (x).begin(), (x).end()
 
const int inf = 9e18;
 
struct DDA {
    int n = 1;
    vector<int> Tree;
 
    DDA (int N) {
        ++N; while (n < N) n <<= 1;
        Tree.resize(2 * n, 0);
    }
 
    void update (int i, int delta){
        for (i += n; i > 0; i >>= 1) Tree[i] += delta;
    }
 
    int query (int l, int r){ // [l, r]
        int res = 0;
        for (l += n, r += n; l <= r; l >>= 1, r >>= 1){
            if (l & 1) res += Tree[l++];
            if (!(r & 1)) res += Tree[r--];
        } return res;
    }
};
 
int32_t main(){
    ios::sync_with_stdio(false); cin.tie(nullptr);
 
    int n, m, q; cin >> n >> m >> q;
    vector<pii> edge(n-1);
    vector<vector<int>> adj(n), Adj(n);
    for (int i = 0; i < n-1; i++){
        int u, v; cin >> u >> v; u--, v--;
        Adj[u].push_back(v); Adj[v].push_back(u);
        edge[i] = pii{u, v};
    }
 
    vector<int> tin(n), tout(n);
    int timer = 0, logn = 2 + log2(n);
    vector<vector<int>> pi(n, vector<int>(logn, 0));
    auto reroot = [&](auto&& self, int s, int parent) -> void{
        tin[s] = timer++; pi[s][0] = parent;
        for (int i = 1; i < logn; i++) pi[s][i] = pi[pi[s][i-1]][i-1];
 
        for (auto u : Adj[s]) if (u != parent){
            adj[s].push_back(u); self(self, u, s); 
        } tout[s] = timer;
    }; reroot(reroot, 0, 0);
 
    while (true) { break; }
 
    auto isAnc = [&](int anc, int u){
        return (tin[anc] <= tin[u] and tout[u] <= tout[anc]);
    };
 
    auto lca = [&](int u, int v){
        if (isAnc(u, v) or isAnc(v, u)) return isAnc(u, v) ? u : v;
        for (int i = logn-1; i > -1; i--){
            if (!isAnc(pi[u][i], v)) u = pi[u][i];
        } return pi[u][0];
    };
 
    for (auto& [u, v] : edge) if (isAnc(v, u)) swap(u, v);
 
    vector<pii> t(m);
    for (int i = 0; i < m; i++){
        int p, c; cin >> p >> c; p--;
        int v = edge[p].ss;
        t[i] = pii{c, v};
    } sort(entire(t));
 
    vector<array<int, 4>> qn(q); // x gold, y silver
    for (auto& [u, v, x, y] : qn) cin >> u >> v >> x >> y, u--, v--;
 
    DDA cnt(n), et(n);
 
    auto psum = [&](int u, int v){
        int anc = lca(u, v), ea = et.query(0, tin[anc]);
        int pu = et.query(0, tin[u]), pv = et.query(0, tin[v]);
        return pu + pv - 2 * ea; 
    };
 
    auto pcnt = [&](int u, int v){
        int anc = lca(u, v), ca = cnt.query(0, tin[anc]);
        int cu = cnt.query(0, tin[u]), cv = cnt.query(0, tin[v]);
        return cu + cv - 2 * ca;
    };
 
    auto add = [&](int i){
        auto [w, v] = t[i];
        et.update(tin[v], +w); et.update(tout[v], -w);
        cnt.update(tin[v], +1); cnt.update(tout[v], -1);
    };
 
    vector<deque<int>> bs(m);
    vector<pii> bound(q, pii{0, m-1});
    vector<int> mcost(q, inf), cmin(q, 0);
 
    for (int i = 0; i < q; i++) bs[m/2].push_back(i);
 
    auto reduce = [&](int i, vector<deque<int>>& nbs){
        auto [u, v, x, y] = qn[i]; 
        auto& [l, r] = bound[i];
        int mid = (l + r + 1) / 2, path = psum(u, v);
        if (!(l < r)){ cmin[i] = pcnt(u, v); mcost[i] = path; return;}
        if (path <= y) l = mid, cmin[i] = pcnt(u, v), mcost[i] = path;
        else r = mid - 1;
        mid = (l + r + 1) / 2; nbs[mid].push_back(i);
    };
 
    int logm = 2 + log2(m);
    for (int depth = 0; depth <= logm; depth++){
        vector<deque<int>> nbs(m);
        fill(entire(cnt.Tree), 0ll); fill(entire(et.Tree), 0ll);
        for (int i = 0; i < m; i++){
            add(i); while (!bs[i].empty()) reduce(bs[i].back(), nbs), bs[i].pop_back();
        } bs = nbs;
    }
 
    fill(entire(cnt.Tree), 0ll); fill(entire(et.Tree), 0ll);
    for (int i = 0; i < m; i++) add(i);
 
    vector<int> ans(q);
    for (int i = 0; i < q; i++){
        auto [u, v, x, y] = qn[i];
        if (mcost[i] <= y) ans[i] = pcnt(u, v) - cmin[i];
        else ans[i] = pcnt(u, v);
        ans[i] = (ans[i] <= x) ? (x - ans[i]) : -1;
    }
 
    for (auto val : ans) cout << val << endl;
    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...