제출 #1341979

#제출 시각아이디문제언어결과실행 시간메모리
1341979dhuyyyyTwo Currencies (JOI23_currencies)C++20
100 / 100
1737 ms48680 KiB
#include <bits/stdc++.h>
#define int long long 
#define fi first
#define se second

using namespace std;

using ii = pair<int,int>;

const int N = 1e5+5;

int n, m, q, u, v, c, gold, silver, sum, cnt, timer = 0;

int sz[N], depth[N], par[N], tin[N], heavy[N], chain[N], L[N], R[N], ans[N];

ii edge[N];

bool ok = 1;

vector <int> adj[N], queries[N];

struct canh{
    int c, u, v;
    bool operator < (const canh &y){
        return c < y.c;
    }
} edges[N];

struct Queries{
    int u, v, gold, silver;
} qr[N];

void DFS(int u,int p){
    sz[u] = 1;
    depth[u] = depth[p] + 1;
    par[u] = p;
    for (int it : adj[u]){
        if (it == p) continue;
        DFS(it,u);
        if (sz[it] > sz[heavy[u]]) heavy[u] = it;
        sz[u] += sz[it];
    }
}
void HLD(int u,int p){
    tin[u] = ++timer;
    if (!heavy[u]) return;
    chain[heavy[u]] = chain[u];
    HLD(heavy[u],u);
    for (int it : adj[u]){
        if (it == p || it == heavy[u]) continue;
        chain[it] = it;
        HLD(it,u);
    }
}

struct BIT{
    vector <int> bit;
    int n;
    BIT (int _n = 0) : n(_n){
        bit.assign(n + 5,0);
    }
    void update(int id,int val){
        while (id <= n){
            bit[id] += val;
            id += id & -id;
        }
    }
    int get(int id){
        int res = 0;
        while (id > 0){
            res += bit[id];
            id -= id & -id;
        }
        return res;
    }
    int query(int l,int r){
        if (l > r) return 0;
        return get(r) - get(l - 1);
    }
    void reset(){
        for (int i = 1; i <= n; i++) bit[i] = 0;
    }
};

struct hld{
    BIT tree;
    int n;
    hld (int _n = 0) : n(_n), tree(BIT(_n)) {}
    int Get(int u,int v){
        int res = 0;
        while (chain[u] != chain[v]){
            if (depth[chain[u]] < depth[chain[v]]) swap(u,v);
            res += tree.query(tin[chain[u]],tin[u]);
            u = par[chain[u]];
        }
        if (depth[u] > depth[v]) swap(u,v);
        res += tree.query(tin[u] + 1,tin[v]);
        return res;
    }
    void up(int u,int v,int val){
        if (depth[u] > depth[v]) swap(u,v);
        tree.update(tin[v],val);
    }
    void reset(){
        tree.reset();
    }
};

signed main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL); cout.tie(NULL);
    cin >> n >> m >> q;
    for (int i = 1; i < n; i++){
        cin >> u >> v;
        adj[u].push_back(v);
        adj[v].push_back(u);
        edge[i] = {u,v};
    }
    for (int i = 1; i <= m; i++){
        cin >> u >> c;
        edges[i] = {c,edge[u].fi,edge[u].se};
    }
    sort(edges+1,edges+1+m);
    for (int i = 1; i <= q; i++){
        cin >> qr[i].u >> qr[i].v >> qr[i].gold >> qr[i].silver;
        L[i] = 0;
        R[i] = m;
        ans[i] = -1;
    }
    chain[1] = 1;
    DFS(1,0);
    HLD(1,0);
    hld Sum(n);
    hld Cnt(n);
    while (ok){
        ok = 0;
        for (int i = 1; i <= q; i++){
            if (L[i] > R[i]) continue;
            ok = 1;
            queries[(L[i] + R[i]) >> 1].push_back(i);
        }
        for (int i = 1; i <= m; i++){
            Cnt.up(edges[i].u,edges[i].v,1);
        }
        for (int i = 0; i <= m; i++){
            if (i){
                Sum.up(edges[i].u,edges[i].v,edges[i].c);
                Cnt.up(edges[i].u,edges[i].v,-1);
            }
            for (int it : queries[i]){
                u = qr[it].u;
                v = qr[it].v;
                gold = qr[it].gold;
                silver = qr[it].silver;
                sum = Sum.Get(u,v);
                cnt = Cnt.Get(u,v);
                if (sum <= silver){
                    ans[it] = max(ans[it],gold - cnt);
                    L[it] = i + 1;
                } else R[it] = i - 1;
            }
            queries[i].clear();
        }
        Sum.reset();
        Cnt.reset();
    }
    for (int i = 1; i <= q; i++){
        cout << ans[i] << '\n';
    }
    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...