Submission #758420

#TimeUsernameProblemLanguageResultExecution timeMemory
758420Jarif_RahmanTwo Currencies (JOI23_currencies)C++17
100 / 100
729 ms51596 KiB
#include <bits/stdc++.h>
#define pb push_back
#define f first
#define sc second
using namespace std;
typedef long long int ll;
typedef string str;

#define int ll

const int K = 19;

struct BIT{
    int n;
    vector<ll> sm;
    BIT(int _n){
        n = _n;
        sm.resize(n);
    }
    void add(int in, ll x){
        in++;
        while(in <= n) sm[in-1]+=x, in+=in&-in;
    }
    void add(int l, int r, ll x){
        add(l, x);
        if(r+1 < n) add(r+1, -x);
    }
    ll get(int in){
        in++;
        ll s = 0;
        while(in >= 1) s+=sm[in-1], in-=in&-in;
        return s;
    }
};

struct query{
    int a, b, c;
    ll g, s;
    int i;
    query(){}
    query(int _a, int _b, int _c, ll _g, ll _s, int _i): a(_a), b(_b), c(_c), g(_g), s(_s), i(_i) {}
};


int n, m, q;
vector<pair<int, ll>> c;
vector<vector<int>> tree;
vector<int> depth, pos, sz;
vector<int> anc[K];
BIT bit1(0), bit2(0);
vector<ll> ans;
vector<pair<int, int>> edges;
vector<query> Q;

int intime = 0;
void dfs(int nd, int ss, int d){
    pos[nd] = intime++;
    depth[nd] = d;
    if(ss != -1) anc[0][nd] = ss;
    for(int x: tree[nd]) if(x != ss) dfs(x, nd, d+1), sz[nd]+=sz[x];
}

int get_anc(int nd, int d){
    for(int i = 0; i < K; i++){
        if(d&1) nd = anc[i][nd];
        d>>=1;
    }
    return nd;
}

int lca(int a, int b){
    if(depth[a] > depth[b]) swap(a, b);
    b = get_anc(b, depth[b]-depth[a]);
    if(a == b) return a;

    for(int i = K-1; i >= 0; i--) if(anc[i][a] != anc[i][b])
        a = anc[i][a], b = anc[i][b];
    return anc[0][a];
}



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

    int n, m, q; cin >> n >> m >> q;

    c.resize(m);
    tree.resize(n);
    depth.resize(n);
    pos.resize(n);
    sz.assign(n, 1);
    fill(anc, anc+K, vector<int>(n, 0));
    bit1 = BIT(n), bit2 = BIT(n);
    ans.resize(q);

    for(int i = 0; i < n-1; i++){
        int a, b; cin >> a >> b; a--, b--;
        tree[a].pb(b);
        tree[b].pb(a);
        edges.pb({a, b});
    }

    dfs(0, -1, 0);
    for(int p = 1; p < K; p++) for(int i = 0; i < n; i++)
        anc[p][i] = anc[p-1][anc[p-1][i]];


    for(auto &[i, x]: c){
        cin >> i >> x, i--;
        auto [a, b] = edges[i];
        if(depth[a] > depth[b]) i = a;
        else i = b;
        bit1.add(pos[i], pos[i]+sz[i]-1, x);
    }
    sort(c.begin(), c.end(), [](pair<int, ll> a, pair<int, ll> b){
        return make_pair(a.sc, a.f) > make_pair(b.sc, b.f);
    });
    c.insert(c.begin(), {0, 0});

    for(int i = 0; i < q; i++){
        int a, b; ll g, s; cin >> a >> b >> g >> s;
        a--, b--;
        int c = lca(a, b);
        a = pos[a], b = pos[b], c = pos[c];
        Q.pb(query(a, b, c, g, s, i));
    }

    function<void(int, int, vector<int>)> pbs = [&](int l, int r, const vector<int>& Qi){
        if(Qi.empty()) return;
        if(l == r){
            bit2.add(pos[c[l].f], pos[c[l].f]+sz[c[l].f]-1, 1);
            for(int i: Qi){
                ans[Q[i].i] = Q[i].g-bit2.get(Q[i].a)-bit2.get(Q[i].b)+bit2.get(Q[i].c)*2;
                ans[Q[i].i] = max(ans[Q[i].i], -1LL);
            }
            bit2.add(pos[c[l].f], pos[c[l].f]+sz[c[l].f]-1, -1);
            return;
        }

        int md = (l+r)/2;
        for(int i = l; i <= md; i++){
            bit1.add(pos[c[i].f], pos[c[i].f]+sz[c[i].f]-1, -c[i].sc);
            bit2.add(pos[c[i].f], pos[c[i].f]+sz[c[i].f]-1, 1);
        }

        vector<int> A, B;
        for(int i: Qi){
            if(bit1.get(Q[i].a)+bit1.get(Q[i].b)-bit1.get(Q[i].c)*2 > Q[i].s) B.pb(i);
            else A.pb(i);
        }

        pbs(md+1, r, B);
        for(int i = l; i <= md; i++){
            bit1.add(pos[c[i].f], pos[c[i].f]+sz[c[i].f]-1, c[i].sc);
            bit2.add(pos[c[i].f], pos[c[i].f]+sz[c[i].f]-1, -1);
        }
        pbs(l, md, A);
    };

    vector<int> Qi;
    for(int i = 0; i < q; i++) Qi.pb(i);
    pbs(0, m, Qi);

    for(ll x: ans) cout << x << "\n";

}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...