Submission #1368324

#TimeUsernameProblemLanguageResultExecution timeMemory
1368324baodatTwo Currencies (JOI23_currencies)C++20
100 / 100
1145 ms33300 KiB
/*
Author: baodat
※\(^o^)/※
Current goal: Training for VNOI shirt
*/
#include <bits/stdc++.h>
using namespace std;
#define ll long long 
#define FOR(i, l, r) for(int i = l; i <= r; i++)
#define FORD(i, l, r) for(int i = l; i >= r; i--)
#define db double
#define ldb long double
#define all_1(x) (x).begin() + 1, (x).end()
#define all(x) (x).begin(), (x).end()
#define ins insert
#define pb push_back
template<typename T>void debug_var(const T& var, const string& name){
    cerr << name << ": " << var << "\n";
}
template<typename T>void debug_1d(const T& vt, const string& name){
    if(vt.empty()){
        cerr << name << " is empty!\n";
        return;
    }
    FOR(i, 0, (int)vt.size() - 1){
        cerr << name << "[" << i << "]: " << vt[i] << "\n";
    }
}
const ll oo = 2e18;
const int N = 1e5 + 5;
const int LOG = 20;
template<typename T> struct BIT{
    int _n;
    vector<T> _bit;
    BIT(int n = 0){
        init(n);
    }  
    void init(int n){
        _n = n;
        _bit.assign(_n + 1, 0);
    }
    void update(int i, T v){
        while(i <= _n){
            _bit[i] += v;
            i += i &-i;
        }
    }
    T query(int i){
        T ans = 0;
        while(i > 0){
            ans += _bit[i];
            i -= i &-i;
        }
        return ans;
    }
    T query(int l, int r){
        return query(r) - query(l - 1);
    }
};

int n, m, q, tin[N], tout[N], timer = 0, lca[N][LOG], depth[N], convert[N];
vector<int> adj[N];
struct Data{
    int pos, val; //station here
}a[N];
bool compare(Data a, Data b){
    return a.val < b.val;
}
struct Data2{
    int u, v;
    ll gold, silver; //query here
};
void dfs(int u, int p){
    tin[u] = ++timer;
    for(int v : adj[u]){
        if(v == p) continue;
        depth[v] = depth[u] + 1;
        lca[v][0] = u;
        dfs(v, u);
    }
    tout[u] = ++timer;
}
int lift(int u, int k){
    FOR(j, 0, LOG - 1) if(k & (1 << j)) u = lca[u][j];
    return u;
}
int LCA(int u, int v){
    if(depth[u] != depth[v]){
        if(depth[u] < depth[v]) swap(u, v);
        u = lift(u, depth[u] - depth[v]);
    }
    if(u == v) return u;
    FORD(j, LOG - 1, 0){
        if(lca[u][j] != lca[v][j]){
            u = lca[u][j];
            v = lca[v][j];
        }
    }
    return lca[u][0];
}
void solve(){
    cin >> n >> m >> q;
    vector<int> U(n + 1), V(n + 1);
    FOR(i, 1, n - 1){
        int u, v;
        cin >> u >> v;
        U[i] = u;
        V[i] = v;
        adj[u].pb(v);
        adj[v].pb(u);
    }
    dfs(1, -1);
    FOR(i, 1, n - 1){
        if(depth[U[i]] > depth[V[i]]) convert[i] = U[i];
        else convert[i] = V[i];
    }
    FOR(j, 1, LOG - 1)FOR(i, 1, n) lca[i][j] = lca[lca[i][j - 1]][j - 1];
    FOR(i, 1, m){
        cin >> a[i].pos >> a[i].val;
    }
    sort(a + 1, + a + 1 + m, compare);
    vector<Data2> queries(q + 1);
    vector<int> L(q + 1, 1), R(q + 1, m), res(q + 1, 0);
    FOR(i, 1, q) cin >> queries[i].u >> queries[i].v >> queries[i].gold >> queries[i].silver; 
    vector<int> amount_station(q + 1);
    BIT<int> bit_cnt(2 * n + 1);
    FOR(i, 1, m){
        bit_cnt.update(tin[convert[a[i].pos]], 1);
        bit_cnt.update(tout[convert[a[i].pos]], -1);
    }
    FOR(i, 1, q){
        auto [u, v, gold, silver] = queries[i];
        amount_station[i] = bit_cnt.query(tin[u]) + bit_cnt.query(tin[v]) - 2 * bit_cnt.query(tin[LCA(u, v)]);
    }
    while(true){
        bool changed = false;
        vector<vector<int>> ds(m + 1);
        FOR(i, 1, q){
            if(L[i] <= R[i]){
                int mid = (L[i] + R[i]) >> 1;
                ds[mid].pb(i);
                changed = true;
            }
        }
        if(!changed)break;
        bit_cnt.init(2 * n + 1);
        BIT<ll> bit_sum(2 * n + 1);
        FOR(mid, 1, m){
            bit_sum.update(tin[convert[a[mid].pos]], a[mid].val);
            bit_cnt.update(tin[convert[a[mid].pos]], 1);
            bit_sum.update(tout[convert[a[mid].pos]], -a[mid].val);
            bit_cnt.update(tout[convert[a[mid].pos]], -1);
            for(int it : ds[mid]){
                auto [u, v, gold, silver] = queries[it];
                int cur = LCA(u, v);
                ll sum = bit_sum.query(tin[u]) + bit_sum.query(tin[v]) - 2ll * bit_sum.query(tin[cur]);
                if(sum <= silver){
                    //can afford
                    res[it] = bit_cnt.query(tin[u]) + bit_cnt.query(tin[v]) - 2ll * bit_cnt.query(tin[cur]);
                    L[it] = mid + 1;
                }
                else R[it] = mid - 1;
            }
        }
    }
    FOR(i, 1, q){
        if(res[i] == -1) cout << "-1\n";
        else{
            int gold_spend = amount_station[i] - res[i];
            if(queries[i].gold < gold_spend) cout << "-1\n";
            else cout << queries[i].gold - gold_spend << "\n";
        } 
    }
}
signed main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    int t = 1;
    //cin >> t;
    while(t--){
        solve();
    }
    return 0;
}
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...