Submission #1308121

#TimeUsernameProblemLanguageResultExecution timeMemory
1308121viobowTwo Currencies (JOI23_currencies)C++17
100 / 100
2097 ms70072 KiB
#include <bits/stdc++.h> #define int long long #define ll long long #define fi first #define se second #define all(x) x.begin(), x.end() #define sz(x) (int)x.size() #define pb push_back #define re exit(0); #define FOR(i, a, b) for(int i = (a), _b = (b); i <= _b; i++) #define FORD(i, a, b) for(int i = (a), _b = (b); i >= _b; i--) #define LOOP(a) for(int i = 0, _a = (a); i < _a; i++) #define left id<<1 #define right id<<1|1 #define _lower(v, x) lower_bound(v.begin(), v.end(), x) - v.begin() + 1 #define ever ;; using namespace std; typedef vector<int> vi; typedef pair<int, int> pii; typedef vector<pii> vii; template<typename T> void chkmin(T &x, T y) {if (y < x) x = y;} template<typename T> void chkmax(T &x, T y) {if (y > x) x = y;} const int mod = 1e9 + 7; void add(int &a, int b) { a += b; if (a >= mod) a -= mod; if (a < 0) a += mod; } int _pow(int a, int b) { int ans = 1; while (b) { if (b % 2 == 1) ans = 1ll * ans * a % mod; a = 1ll * a * a % mod; b /= 2; } return ans; } //-------------------------------------------------------------------------------------------------------------------------------------- const int maxn = 2e5; struct Edge { int u, v, check_point_count; }; struct CheckPoint { int u, v, w; bool operator< (const CheckPoint &other) const { return w < other.w; } }; struct Que { int s, t, gold, silver; }; struct Fenwick_Tree { int BIT[maxn + 5]; int n; void init(int _n) { n = _n; FOR(i, 0, n + 2) BIT[i] = 0; } void update(int pos, int val) { while (pos <= n) { BIT[pos] += val; pos += pos & -pos; } } void update(int l, int r, int val) { update(l, val); update(r + 1, -val); } int get(int pos) { int res = 0; while (pos) { res += BIT[pos]; pos -= pos & -pos; } return res; } }; vii adjList[maxn + 5]; bool costed[maxn + 5]; Edge e[maxn + 5]; CheckPoint cp[maxn + 5]; Que query[maxn + 5]; int n, numCheckPoint, numQuery; vector<int> bucket[maxn + 5]; int l[maxn + 5], r[maxn + 5], silver_road[maxn + 5]; Fenwick_Tree sum_cost, sum_used; int timeDfs, tin[maxn + 5], tout[maxn + 5], dep[maxn + 5], check_point_dep[maxn + 5], par[maxn + 5][20]; void pre_dfs(int u, int p) { tin[u] = ++timeDfs; for (auto [v, check_point_count] : adjList[u]) if (v != p) { dep[v] = dep[u] + 1; check_point_dep[v] = check_point_dep[u] + check_point_count; par[v][0] = u; for (int i = 1; i <= 18; i++) par[v][i] = par[par[v][i - 1]][i - 1]; pre_dfs(v, u); } tout[u] = timeDfs; } int lca(int u, int v) { if (dep[u] < dep[v]) swap(u, v); int h = dep[u] - dep[v]; for (int i = 0; i <= 18; i++) if (h >> i & 1) u = par[u][i]; if (u == v) return u; for (int i = 18; i >= 0; i--) if (par[u][i] != par[v][i]) u = par[u][i], v = par[v][i]; return par[u][0]; } int check_point_count_on_path(int u, int v) { return check_point_dep[u] + check_point_dep[v] - 2 * check_point_dep[lca(u, v)]; } int used_on_path(int u, int v) { return sum_used.get(tin[u]) + sum_used.get(tin[v]) - 2 * sum_used.get(tin[lca(u, v)]); } int cost_on_path(int u, int v) { return sum_cost.get(tin[u]) + sum_cost.get(tin[v]) - 2 * sum_cost.get(tin[lca(u, v)]); } signed main() { ios::sync_with_stdio(0); cin.tie(0); //#define name "mooo" //if (fopen(name".inp", "r")) { // freopen(name".inp", "r", stdin); // freopen(name".out", "w", stdout); //} cin >> n >> numCheckPoint >> numQuery; FOR(i, 1, n - 1) { int u, v; cin >> u >> v; e[i] = {u, v, 0}; } FOR(i, 1, numCheckPoint) { int idx, w; cin >> idx >> w; int u = e[idx].u, v = e[idx].v; e[idx].check_point_count += 1; cp[i] = {u, v, w}; } FOR(i, 1, n - 1) { auto [u, v, check_point_count] = e[i]; adjList[u].pb({v, check_point_count}); adjList[v].pb({u, check_point_count}); } pre_dfs(1, 0); FOR(i, 1, numCheckPoint) { auto& [u, v, w] = cp[i]; if (par[v][0] != u) swap(u, v); } sort(cp + 1, cp + numCheckPoint + 1); FOR(i, 1, numQuery) { int s, t, gold, silver; cin >> s >> t >> gold >> silver; query[i] = {s, t, gold, silver}; } FOR(i, 1, numQuery) l[i] = 1, r[i] = numCheckPoint; bool process = 0; for(ever) { process = 0; FOR(i, 1, numQuery) if (l[i] <= r[i]) process = 1; if (!process) break; //reset stuff FOR(i, 1, numCheckPoint) bucket[i].clear(); sum_cost.init(n); sum_used.init(n); // FOR(i, 1, numQuery) if (l[i] <= r[i]) bucket[(l[i] + r[i]) >> 1].pb(i); for (int bound = 1; bound <= numCheckPoint; bound++) { int v = cp[bound].v, w = cp[bound].w; sum_cost.update(tin[v], tout[v], +w); sum_used.update(tin[v], tout[v], +1); for (int queryID : bucket[bound]) { auto [s, t, gold, silver] = query[queryID]; if (cost_on_path(s, t) <= silver) silver_road[queryID] = used_on_path(s, t), l[queryID] = bound + 1; else r[queryID] = bound - 1; } } } FOR(queryID, 1, numQuery) { auto [s, t, gold, silver] = query[queryID]; int gold_road = check_point_count_on_path(s, t) - silver_road[queryID]; int res = gold - gold_road; if (res < 0) res = -1; cout << res << '\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...