Submission #930817

#TimeUsernameProblemLanguageResultExecution timeMemory
930817alextodoranTwo Currencies (JOI23_currencies)C++17
0 / 100
3 ms11864 KiB
/**
 _  _   __  _ _ _  _  _ _
 |a  ||t  ||o    d | |o  |
| __    _| | _ | __|  _ |
| __ |/_  | __  /__\ / _\|

**/

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N_MAX = 100000;
const int M_MAX = 100000;
const int Q_MAX = 100000;
const int SILVER_MAX = 1000000000;
const int LOG2_N = 17;

int N, M, Q;
int edge_u[N_MAX + 2], edge_v[N_MAX + 2];
vector <int> adj[N_MAX + 2];
int cpt_edge[M_MAX + 2], cpt_silver[M_MAX + 2];
int qry_start[Q_MAX + 2], qry_finish[Q_MAX + 2];
int qry_gold[Q_MAX + 2]; ll qry_silver[Q_MAX + 2];

int parent[N_MAX + 2], depth[N_MAX + 2];;
int label[N_MAX + 2], max_label[N_MAX + 2];
int curr_label;

void dfs (int u) {
    max_label[u] = label[u] = ++curr_label;
    for (int v : adj[u]) {
        if (v != parent[u]) {
            parent[v] = u;
            depth[v] = depth[u] + 1;
            dfs(v);
            max_label[u] = max(max_label[u], max_label[v]);
        }
    }
}

int ancestor[N_MAX + 2][LOG2_N];

int find_ancestor (int u, int k) {
    for (int t = 0; t < LOG2_N; t++) {
        if ((k >> t) & 1) {
            u = ancestor[u][t];
        }
    }
    return u;
}

int find_lca (int u, int v) {
    if (depth[u] > depth[v]) {
        u = find_ancestor(u, depth[u] - depth[v]);
    }
    if (depth[v] > depth[u]) {
        v = find_ancestor(v, depth[v] - depth[u]);
    }
    if (u == v) {
        return u;
    }
    for (int t = LOG2_N - 1; t >= 0; t--) {
        if (ancestor[u][t] != ancestor[v][t]) {
            u = ancestor[u][t];
            v = ancestor[v][t];
        }
    }
    return parent[u];
}

int lower[Q_MAX + 2], higher[Q_MAX + 2];
int mid[Q_MAX + 2]; ll sum[Q_MAX + 2]; int cnt[Q_MAX + 2];

int cpt_order[M_MAX + 2];
int qry_order[Q_MAX + 2];

ll Fenwick_sum[N_MAX + 2]; int Fenwick_cnt[N_MAX + 2];

void update (int pos, int val) {
    for (int i = pos; i <= N; i += i & -i) {
        Fenwick_sum[i] += val;
        Fenwick_cnt[i] += (val > 0 ? +1 : -1);
    }
}
void update (int l, int r, int val) {
    update(l, +val); update(r + 1, -val);
}
pair <ll, int> query (int pos) {
    ll sum = 0; int cnt = 0;
    for (int i = pos; i >= 1; i -= i & -i) {
        sum += Fenwick_sum[i];
        cnt += Fenwick_cnt[i];
    }
    return make_pair(sum, cnt);
}

void step () {
    iota(cpt_order + 1, cpt_order + M + 1, 1);
    iota(qry_order + 1, qry_order + Q + 1, 1);
    sort(cpt_order + 1, cpt_order + M + 1, [&] (const int &i, const int &j) {
        return cpt_silver[i] < cpt_silver[j];
    });
    sort(qry_order + 1, qry_order + Q + 1, [&] (const int &i, const int &j) {
        return qry_silver[i] < qry_silver[j];
    });
    fill(Fenwick_sum + 1, Fenwick_sum + N + 1, 0);
    fill(Fenwick_cnt + 1, Fenwick_cnt + N + 1, 0);
    for (int i = 1, j = 0; i <= Q && mid[qry_order[i]] != INT_MAX; i++) {
        while (j + 1 <= M && cpt_silver[cpt_order[j + 1]] <= mid[qry_order[i]]) {
            int e = cpt_edge[cpt_order[++j]];
            update(label[edge_v[e]], max_label[edge_v[e]], cpt_silver[cpt_order[j]]);
        }
        int u = qry_start[qry_order[i]], v = qry_finish[qry_order[i]];
        int lca = find_lca(u, v);
        ll sum_u; int cnt_u; tie(sum_u, cnt_u) = query(label[u]);
        ll sum_v; int cnt_v; tie(sum_v, cnt_v) = query(label[v]);
        ll sum_lca; int cnt_lca; tie(sum_lca, cnt_lca) = query(label[lca]);
        sum[qry_order[i]] = sum_u + sum_v - 2 * sum_lca;
        cnt[qry_order[i]] = cnt_u + cnt_v - 2 * cnt_lca;
    }
}

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

    cin >> N >> M >> Q;
    for (int i = 1; i <= N - 1; i++) {
        cin >> edge_u[i] >> edge_v[i];
        adj[edge_u[i]].push_back(edge_v[i]);
        adj[edge_v[i]].push_back(edge_u[i]);
    }
    dfs(1);
    for (int u = 1; u <= N; u++) {
        ancestor[u][0] = parent[u];
    }
    for (int t = 1; t < LOG2_N; t++) {
        for (int u = 1; u <= N; u++) {
            ancestor[u][t] = ancestor[ancestor[u][t - 1]][t - 1];
        }
    }
    for (int i = 1; i <= N - 1; i++) {
        if (edge_u[i] != parent[edge_v[i]]) {
            swap(edge_u[i], edge_v[i]);
        }
    }
    for (int i = 1; i <= M; i++) {
        cin >> cpt_edge[i] >> cpt_silver[i];
    }
    for (int i = 1; i <= Q; i++) {
        cin >> qry_start[i] >> qry_finish[i];
        cin >> qry_gold[i] >> qry_silver[i];
        lower[i] = 0; higher[i] = SILVER_MAX;
    }
    while (true) {
        bool done = true;
        for (int i = 1; i <= Q; i++) {
            if (lower[i] < higher[i]) {
                done = false;
                mid[i] = (lower[i] + higher[i] + 1) / 2;
                cnt[i] = 0;
            } else {
                mid[i] = INT_MAX; // done
            }
        }
        if (done == true) {
            break;
        }
        step();
        for (int i = 1; i <= Q; i++) {
            if (mid[i] != INT_MAX) {
                if (sum[i] <= qry_silver[i]) {
                    lower[i] = mid[i];
                } else {
                    higher[i] = mid[i] - 1;
                }
            }
        }
    }
    for (int i = 1; i <= Q; i++) {
        mid[i] = lower[i];
    }
    step();
    fill(Fenwick_sum + 1, Fenwick_sum + N + 1, 0);
    fill(Fenwick_cnt + 1, Fenwick_cnt + N + 1, 0);
    for (int i = 1; i <= M; i++) {
        int e = cpt_edge[i];
        update(label[edge_v[e]], max_label[edge_v[e]], cpt_silver[i]);
    }
    for (int i = 1; i <= Q; i++) {
        int u = qry_start[i], v = qry_finish[i];
        int lca = find_lca(u, v);
        int total_cpt = query(label[u]).second + query(label[v]).second - 2 * query(label[lca]).second;
        int with_silver = cnt[i];
        if (with_silver < total_cpt) {
            with_silver += min((ll) (total_cpt - with_silver), (qry_silver[i] - sum[i]) / (mid[i] + 1));
        }
        int with_gold = total_cpt - with_silver;
        cout << (with_gold <= qry_gold[i] ? qry_gold[i] - with_gold : -1) << "\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...