Submission #944673

#TimeUsernameProblemLanguageResultExecution timeMemory
944673phoenix0423Two Currencies (JOI23_currencies)C++17
100 / 100
1526 ms421356 KiB
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> pll;
#define fastio ios::sync_with_stdio(false), cin.tie(0);
#pragma GCC optimize("Ofast,unroll-loops")
#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
#define pb push_back
#define eb emplace_back
#define f first
#define s second
#define int long long
#define lowbit(x) x&-x
const int maxn = 1e5 + 5;
const int INF = 1e9 + 7;
vector<int> adj[maxn];
pll road[maxn];
int sz[maxn], dep[maxn], id[maxn], loc[maxn], par[maxn];
int in[maxn], out[maxn];
int head[maxn];
int cnt = 0, dfn = 0;
int n, m, q;

pll operator + (pll a, pll b){
    return pll(a.f + b.f, a.s + b.s);
}
pll operator - (pll a, pll b){
    return pll(a.f - b.f, a.s - b.s);
}
void operator += (pll &a, pll b){
    a.f += b.f, a.s += b.s;
}
struct BITree{
    pll BIT[maxn * 2];
    void upd(int pos, pll val){
        while(pos < maxn * 2){
            BIT[pos] += val;
            pos += lowbit(pos);
        }
    }
    pll qry(int pos){
        pll ret = {0, 0};
        while(pos > 0){
            ret += BIT[pos];
            pos -= lowbit(pos);
        }
        return ret;
    }
} st;

void dfs(int pos, int prev){
    if(prev != -1) adj[pos].erase(find(adj[pos].begin(), adj[pos].end(), prev));
    in[pos] = ++dfn;
    sz[pos] = 1;
    for(auto &x : adj[pos]){
        dep[x] = dep[pos] + 1;
        par[x] = pos;
        dfs(x, pos);
        if(sz[x] > sz[adj[pos][0]]) swap(x, adj[pos][0]);
    }
    out[pos] = ++dfn;
}

void decompose(int pos, int h){
    head[pos] = h;
    // id[pos] = ++cnt, loc[cnt] = pos;
    for(auto x : adj[pos]){
        if(x == adj[pos][0]) decompose(x, h);
        else decompose(x, x);
    }
}

struct info{
    int s, t, x, y, id;
    info(){}
    info(int _s, int _t, int _x, int _y, int _id) : s(_s), t(_t), x(_x), y(_y), id(_id){}
};

int lca(int a, int b){
    while(head[a] != head[b]){
        if(dep[head[a]] > dep[head[b]]) swap(a, b);
        b = par[head[b]];
    }
    if(dep[a] > dep[b]) swap(a, b);
    return a;
}
pll solve(int s, int t){
    int lc = lca(s, t);
    return st.qry(in[s]) + st.qry(in[t]) - st.qry(in[lc]) - st.qry(in[lc]);
}
pll lok[maxn]; // 剛好可以 max. amount of gold coins 
pll bad[maxn]; // 剛好不行

void bs(vector<pll> a, vector<info> rng, int l, int r){
    if(!rng.size()) return;
    if(l + 1 == r || !a.size()){
        for(auto [s, t, x, y, id] : rng){
            lok[id] = solve(s, t);
        }
        return;
    }
    int m = (l + r) / 2;
    vector<pll> a1, a2, nax;    
    for(auto [c, p] : a){
        auto [x, y] = road[p];
        if(dep[x] < dep[y]) swap(x, y);
        if(c > m) a2.eb(c, p);
        else{
            a1.eb(c, p);
            st.upd(in[x], {c, 1});
            st.upd(out[x], {-c, -1});
        }
        if(c == m) nax.eb(c, p);
    }
    vector<info> r1, r2;
    for(auto [s, t, x, y, id] : rng){
        auto [cnt, ttl] = solve(s, t);
        if(y >= cnt) r2.pb(info(s, t, x, y, id));
        else bad[id] = {cnt, ttl}, r1.pb(info(s, t, x, y, id));
    }
    bs(a2, r2, m, r);
    for(auto [c, p] : a1){
        auto [x, y] = road[p];
        if(dep[x] < dep[y]) swap(x, y);
        st.upd(in[x], {-c, -1});
        st.upd(out[x], {c, 1});
    }
    bs(a1, r1, l, m);
}
int ans[maxn];

signed main(void){
    fastio;
    cin>>n>>m>>q;
    for(int i = 0; i < n - 1; i++){
        int a, b;
        cin>>a>>b;
        a--, b--;
        adj[a].pb(b);
        adj[b].pb(a);
        road[i] = {a, b};
    }
    vector<pll> a(m);
    for(int i = 0; i < m; i++){
        cin>>a[i].s>>a[i].f;
        a[i].s--;
    }
    sort(a.begin(), a.end());
    vector<info> qry;
    for(int i = 0; i < q; i++){
        int s, t, x, y;
        cin>>s>>t>>x>>y;
        s--, t--;
        qry.pb(info(s, t, x, y, i));
    }
    dfs(0, -1);
    decompose(0, 0);
    vector<pll> empt;
    bs(a, qry, 0, INF);
    for(int i = 0; i < m; i++){
        auto [c, p] = a[i];
        auto [b, d] = road[p];
        if(dep[b] < dep[d]) swap(b, d);
        st.upd(in[b], {0, 1});
        st.upd(out[b], {0, -1});
    }
    for(int i = 0; i < q; i++){
        auto [s, t, x, y, id] = qry[i];
        auto [c1, t1] = lok[i];
        auto [c2, t2] = bad[i];
        if(t2 <= t1){
            ans[i] = x + t1 - solve(s, t).s;
            continue;
        }
        int cnt = (c2 - c1) / (t2 - t1);
        int canuse = (y - c1) / cnt;
        ans[i] += x + t1 + canuse - solve(s, t).s;
    }
    for(int i = 0; i < q; i++){
        cout<<(ans[i] < 0 ? -1 : ans[i])<<"\n";
    }
}  
/*
4 5 2
1 2
2 3
3 4
1 5
2 6
3 7
*/
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...