Submission #1161224

#TimeUsernameProblemLanguageResultExecution timeMemory
1161224brintonTwo Currencies (JOI23_currencies)C++20
100 / 100
765 ms77060 KiB
#include <bits/stdc++.h>
using namespace std;
#define int long long
struct dataS{
    // now is bit
    private:
    vector<int> tree;
    int N;
    int query(int idx){
        int ans = 0;
        for(int i = idx;i >= 1;i -= i&-i){
            ans += tree[i];
        }
        return ans;
    }
    public:
    dataS(int iN){
        N = iN;
        tree.resize(N+1);
    } 
    void modify(int idx,int dv){
        for(int i = idx;i <= N;i += i&-i){
            tree[i] += dv;
        }
    }
    int query(int u,int v){
        if(u > v)swap(u,v);
        return query(v)-query(u);
    }
};
// ===== hld ====
vector<vector<int>> edges;
vector<int> sz,par,dep,hson,rdn,top;
int dfs1(int cur,int p,int cdep){
    par[cur] = p;
    dep[cur] = cdep;
    int csz = 1;
    int maxSz = 0;
    int maxIdx = -1;
    for(auto nxt:edges[cur]){
        if(nxt == p)continue;
        int nsz = dfs1(nxt,cur,cdep+1);
        if(nsz > maxSz){
            maxSz = nsz;
            maxIdx = nxt;
        }
        csz += nsz;
    }
    hson[cur] = maxIdx;
    return csz;
}
int gt = 1;
void dfs2(int cur,int p){
    // dfs child first
    rdn[cur] = gt;
    gt++;
    if(hson[cur] != -1){
        top[hson[cur]] = top[cur];
        dfs2(hson[cur],cur);
    }
    for(auto nxt:edges[cur]){
        if(nxt == p)continue;
        if(nxt == hson[cur])continue;
        top[nxt] = nxt;
        dfs2(nxt,cur);
    }
}
int hld_q(int u,int v,dataS& bit){
    int ans = 0;
    while(top[u] != top[v]){
        // cout << u << " " << v << endl;
        if(dep[top[u]] > dep[top[v]]){
            // lift up u
            ans += bit.query(rdn[top[u]]-1,rdn[u]);// -1 because top[u]'s parent consider
            
            u = par[top[u]];
        }else{
            ans += bit.query(rdn[top[v]]-1,rdn[v]);// -1 because top[u]'s parent consider

            v = par[top[v]];
        }
    }
    ans += bit.query(rdn[u],rdn[v]);
    return ans;
}
void hld_m(int u,int v,int dv,dataS& bit){// modify in child
    if(par[u] == v){
        // modify u
        // cout << "modify" << rdn[u] << endl;
        bit.modify(rdn[u],dv);
    }else{
        // modify v
        // cout << "modify" << rdn[v] << endl;
        bit.modify(rdn[v],dv);
    }
}
signed main(){
    cin.tie(0);
    ios_base::sync_with_stdio(0);
    //start here
    int N,C,Q;
    cin >> N >> C >> Q;
    // ==== input tree ===
    edges.resize(N+1);
    vector<array<int,2>> edgeUV;
    for(int i = 0;i < N-1;i++){
        int a,b;
        cin >> a >> b;
        edges[a].push_back(b);
        edges[b].push_back(a);
        edgeUV.push_back({a,b});
    }
    sz = par = dep = hson = rdn = top = vector<int>(N+1,0);
    dfs1(1,-1,0);
    top[1] = 1;
    dfs2(1,-1);
    // for(int i = 1;i <= N;i++)cout << rdn[i] << " ";cout << endl;
    // for(int i = 1;i <= N;i++)cout << top[i] << " ";cout << endl;
    // ==== input checkPoint ====
    vector<array<int,3>> checkP;// cost,u,v
    for(int i = 0;i < C;i++){
        int loc,cost;
        cin >> loc >> cost;
        loc--;
        checkP.push_back({cost,edgeUV[loc][0],edgeUV[loc][1]});
    }
    // ===== query input offline ====
    vector<array<int,5>> qry;
    for(int i = 0;i < Q;i++){
        int u,v,g,s;
        cin >> u >> v >> g >> s;
        qry.push_back({u,v,g,s,i});
    }
    // ==== sort CheckPoint ====
    sort(checkP.begin(),checkP.end());
    vector<int> ans(Q);
    dataS silver(N+1);
    dataS gold(N+1);
    dataS change(N+1);
    for(auto [cost,a,b]:checkP){
        // gold.modify(a,b,1);
        hld_m(a,b,1,gold);
    }
    // for(int u = 1;u <= N;u++){
    //     for(int v = u;v <= N;v++){
    //         cout << u << " " << v << ":" << hld_q(u,v,gold) << endl;
    //     }
    // }
    // cout << hld_q(1,3,gold) << endl;
    // return 0;
    auto whole = [&](int l,int r,vector<array<int,5>> cq,auto whole){
        if(l > r){
            // answer queries;
            for(auto [u,v,g,s,idx]:cq){
                
                // cout << idx << ":" << gold.query(u,v) << " " << change.query(u,v) << endl;
                // cout << idx << ":" << hld_q(u,v,gold) << " " << hld_q(u,v,change) << endl;
                // ans[idx] = max(-1LL,g-(gold.query(u,v)-change.query(u,v)));
                ans[idx] = max(-1LL,g-(hld_q(u,v,gold)-hld_q(u,v,change)));
            }
            return;
        }
        // put half queries in
        int m = (l+r)/2;
        for(int i = l;i <= m;i++){
            // ! full point change to hld
            // change.modify(checkP[i][1],checkP[i][2],1);
            // silver.modify(checkP[i][1],checkP[i][2],checkP[i][0]);
            hld_m(checkP[i][1],checkP[i][2],1,change);
            hld_m(checkP[i][1],checkP[i][2],checkP[i][0],silver);
        }
        vector<array<int,5>> ql,qr;
        for(auto [u,v,g,s,idx]:cq){
            // bool ok = silver.query(u,v) <= s;
            bool ok = hld_q(u,v,silver) <= s;
            if(ok){
                qr.push_back({u,v,g,s,idx});
            }else{
                ql.push_back({u,v,g,s,idx});
            }
        }
        whole(m+1,r,qr,whole);
        // remove;
        for(int i = l;i <= m;i++){
            // ! full point change to hld
            // change.modify(checkP[i][1],checkP[i][2],-1);
            // silver.modify(checkP[i][1],checkP[i][2],-checkP[i][0]);
            hld_m(checkP[i][1],checkP[i][2],-1,change);
            hld_m(checkP[i][1],checkP[i][2],-checkP[i][0],silver);
        }
        whole(l,m-1,ql,whole);
    };
    whole(0,C-1,qry,whole);
    for(auto i:ans)cout << i << "\n";
}
// 整體2分
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...