제출 #1308108

#제출 시각아이디문제언어결과실행 시간메모리
1308108sweetwibu2k8Two Currencies (JOI23_currencies)C++20
0 / 100
2 ms976 KiB
#include <bits/stdc++.h> using namespace std; #define endl "\n" #define fi first #define se second #define pb push_back #define all(x) x.begin(), x.end() typedef long long ll; typedef pair<int,int> pii; const int M = 1e5 + 6; int n, m, q; vector<int> g[M]; pii e[M]; int cost[M], in[M], out[M]; int anc[M][18], depth[M]; int d[M], ini[M], Lca[M]; int timedfs = 0; ll L[M], R[M], MID[M], ans[M]; struct query { int s, t; ll x, y; } Q[M]; struct Fenwick { ll f[M]; int n; void resize(int x) { n = x; fill(f, f + n + 1, 0); } void update(int i, int val) { for (; i <= n; i += i & -i) f[i] += val; } ll GET(int i) { ll res = 0; for (; i > 0; i -= i & -i) res += f[i]; return res; } } BIT, CNT; void dfs(int u, int p) { in[u] = ++timedfs; anc[u][0] = p; for (int v : g[u]) { if (v == p) continue; depth[v] = depth[u] + 1; dfs(v, u); } out[u] = timedfs; } int get_lca(int u, int v) { if (depth[u] < depth[v]) swap(u, v); for (int k = 17; k >= 0; k--) if (depth[u] - (1 << k) >= depth[v]) u = anc[u][k]; if (u == v) return u; for (int k = 17; k >= 0; k--) if (anc[u][k] != anc[v][k]) { u = anc[u][k]; v = anc[v][k]; } return anc[u][0]; } void prework(int u, int p) { for (int v : g[u]) { if (v == p) continue; d[v] += d[u]; prework(v, u); } } int main() { ios_base::sync_with_stdio(false); cin.tie(0); if (!(cin >> n >> m >> q)) return 0; for (int i = 1; i < n; i++) { int u, v; cin >> u >> v; g[u].pb(v); g[v].pb(u); e[i] = {u, v}; } memset(cost, -1, sizeof(cost)); for (int i = 1; i <= m; i++) { int p, c; cin >> p >> c; cost[p] = c; } dfs(1, 0); for (int k = 1; k < 18; k++) for (int i = 1; i <= n; i++) anc[i][k] = anc[anc[i][k-1]][k-1]; // Đảm bảo e[i].se luôn là nút con for (int i = 1; i < n; i++) if (depth[e[i].fi] > depth[e[i].se]) swap(e[i].fi, e[i].se); vector<int> id; for (int i = 1; i < n; i++) { if (cost[i] != -1) { id.pb(i); d[e[i].se] = 1; // Đánh dấu cạnh có thể sử dụng } } sort(all(id), [](int a, int b) { return cost[a] < cost[b]; }); prework(1, 0); for (int i = 1; i <= q; i++) { cin >> Q[i].s >> Q[i].t >> Q[i].x >> Q[i].y; Lca[i] = get_lca(Q[i].s, Q[i].t); ini[i] = d[Q[i].s] + d[Q[i].t] - 2 * d[Lca[i]]; L[i] = 0; R[i] = 1e9; ans[i] = Q[i].x - ini[i]; // Mặc định là x trừ đi tổng số cạnh có giá (chưa khôi phục cái nào) } while (true) { vector<int> queries; for (int i = 1; i <= q; i++) if (L[i] <= R[i]) queries.pb(i); if (queries.empty()) break; sort(all(queries), [](int a, int b) { return (L[a] + R[a]) / 2 < (L[b] + R[b]) / 2; }); BIT.resize(n); CNT.resize(n); int pt = 0; for (int i : queries) { ll mid = (L[i] + R[i]) / 2; while (pt < id.size() && cost[id[pt]] <= mid) { int v = e[id[pt]].se; BIT.update(in[v], cost[id[pt]]); BIT.update(out[v] + 1, -cost[id[pt]]); CNT.update(in[v], 1); CNT.update(out[v] + 1, -1); pt++; } ll current_cost = BIT.GET(in[Q[i].s]) + BIT.GET(in[Q[i].t]) - 2 * BIT.GET(in[Lca[i]]); ll count_edges = CNT.GET(in[Q[i].s]) + CNT.GET(in[Q[i].t]) - 2 * CNT.GET(in[Lca[i]]); if (current_cost <= Q[i].y) { ans[i] = Q[i].x - ini[i] + count_edges; L[i] = mid + 1; } else { R[i] = mid - 1; } } } for (int i = 1; i <= q; i++) { cout << (ans[i] < 0 ? -1 : ans[i]) << endl; } 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...