Submission #1248714

#TimeUsernameProblemLanguageResultExecution timeMemory
1248714enxiayyTwo Currencies (JOI23_currencies)C++20
100 / 100
2106 ms53556 KiB
#include <bits/stdc++.h> #define eb emplace_back #define all(x) x.begin(), x.end() #define compact(v) v.erase(unique(all(v)), v.end()) #define dbg(v) "[" #v " = " << (v) << "]" #define el "\n" using namespace std; typedef long long ll; typedef long double ld; mt19937_64 rng(chrono::high_resolution_clock::now().time_since_epoch().count()); long long randRange(long long l, long long r){ return uniform_int_distribution<long long>(l,r)(rng); } const int N = 2e5 + 5; const int LOG = 20; int n, m, q; vector <int> adj[N]; int p[N], c[N]; pair<int, int> tmp[N]; int L[N], R[N], ANS[N]; struct edge { int u, v; ll cost; edge(int u = 0, int v = 0, ll cost = 0) : u(u), v(v), cost(cost) {} bool operator < (const edge& o) const { return cost < o.cost; } }; edge edges[N]; int lft[N][LOG + 5], chain_id[N], head_chain[N], high[N], tin[N], tout[N], sz[N], timer = 0, cur_chain = 0; struct BIT { vector <ll> bit; int n; BIT(int n = 0) : n(n), bit(n + 5, 0) {} void update(int pos, ll val) { while(pos <= n) { bit[pos] += val; pos += pos & -pos; } } void upd(int l, int r, ll val) { if (l > r) return; update(r, val); } ll get(int pos) { ll res = 0; while(pos) { res += bit[pos]; pos -= pos & -pos; } return res; } ll query(int l, int r) { return get(r) - get(l - 1); } void reset() { for(int i = 0; i <= n; ++i) bit[i] = 0; } }; void dfs_lca(int u) { sz[u] = 1; for(int v : adj[u]) { if (v == lft[u][0]) continue; high[v] = high[u] + 1; lft[v][0] = u; dfs_lca(v); sz[u] += sz[v]; } } namespace LCA { void prepare_lca() { dfs_lca(1); high[0] = -1; for(int j = 1; j <= LOG; ++j) { for(int i = 1; i <= n; ++i) { lft[i][j] = lft[lft[i][j - 1]][j - 1]; } } } int get_lca(int u, int v) { if (high[u] < high[v]) swap(u, v); int k = high[u] - high[v]; for(int i = 0; (1 << i) <= k; ++i) { if (k >> i & 1) { u = lft[u][i]; } } if (u == v) return u; for(int i = LOG; i >= 0; --i) { if (lft[u][i] != lft[v][i]) { u = lft[u][i]; v = lft[v][i]; } } return lft[u][0]; } } using namespace LCA; void build_hld(int u, int par) { if (head_chain[cur_chain] == 0) { head_chain[cur_chain] = u; } chain_id[u] = cur_chain; tin[u] = ++timer; int fat = -1; for(int v : adj[u]) { if (v == par) continue; if (fat == -1 || sz[fat] < sz[v]) { fat = v; } } if (fat != -1) build_hld(fat, u); for(int v : adj[u]) { if (v == par || v == fat) continue; ++cur_chain; build_hld(v, u); } tout[u] = timer; } void prepare_hld() { prepare_lca(); build_hld(1, -1); } struct HLD { BIT ft; int n; HLD(int n = 0) : n(n), ft(BIT(n)) {} ll query_hld(int u, int v) { int lca = get_lca(u, v); ll res = 0; while(chain_id[u] != chain_id[lca]) { res += ft.query(tin[head_chain[chain_id[u]]], tin[u]); u = lft[head_chain[chain_id[u]]][0]; } while(chain_id[v] != chain_id[lca]) { res += ft.query(tin[head_chain[chain_id[v]]], tin[v]); v = lft[head_chain[chain_id[v]]][0]; } if (high[u] < high[v]) res += ft.query(tin[u] + 1, tin[v]); else res += ft.query(tin[v] + 1, tin[u]); return res; } void update_hld(int u, int v, ll val) { int lca = get_lca(u, v); // cerr << u << " " << " " << v << el; // cerr << lca << el; // cerr << "_____________________" << el; while(chain_id[u] != chain_id[lca]) { ft.upd(tin[head_chain[chain_id[u]]], tin[u], val); // cerr << "%%%" << el; // cerr << head_chain[chain_id[u]] << " " << u << el; // cerr << tin[head_chain[chain_id[u]]] << " " << tin[u] << el; // cerr << "%%%" << el; u = lft[head_chain[chain_id[u]]][0]; } while(chain_id[v] != chain_id[lca]) { ft.upd(tin[head_chain[chain_id[v]]], tin[v], val); // cerr << "%%%" << el; // cerr << head_chain[chain_id[v]] << " " << v << el; // cerr << tin[head_chain[chain_id[v]]] << " " << tin[v] << el; // cerr << "%%%" << el; v = lft[head_chain[chain_id[v]]][0]; } // cerr << "LAST: " << el; // cerr << high[u] << " " << high[v] << el; // cerr << query_hld(1, 10) << el; if (high[u] < high[v]) ft.upd(tin[u] + 1, tin[v], val); else ft.upd(tin[v] + 1, tin[u], val); } void reset() { ft.reset(); } }; struct query { int s, t, x, id; ll y; query(int s = 0, int t = 0, int x = 0, ll y = 0, int id = 0) : s(s), t(t), x(x), y(y), id(id) {} } eq[N]; vector <int> queries[N]; void solve() { cin >> n >> m >> q; for(int i = 1; i < n; ++i) { int u, v; cin >> u >> v; adj[u].eb(v); adj[v].eb(u); tmp[i] = {u, v}; } for(int i = 1; i <= m; ++i) { cin >> p[i] >> c[i]; edges[i] = edge(tmp[p[i]].first, tmp[p[i]].second, c[i]); } sort(edges + 1, edges + 1 + m); for(int i = 1; i <= q; ++i) { cin >> eq[i].s >> eq[i].t >> eq[i].x >> eq[i].y; eq[i].id = i; } for(int i = 1; i <= q; ++i) { L[i] = 0; R[i] = m; ANS[i] = -1; } prepare_hld(); HLD hld1(n), hld2(n); // for(int i = 1; i <= m; ++i) { // cerr << edges[i].u << " " << edges[i].v << " " << edges[i].cost << el; // } // cerr << el; // hld1.update_hld(edges[1].u, edges[1].v, edges[1].cost); while(true) { bool finished = true; for(int i = 1; i <= q; ++i) { if (L[i] <= R[i]) { queries[(L[i] + R[i]) >> 1].push_back(i); finished = false; } } if (finished == true) break; for(int i = 1; i <= m; ++i) { hld2.update_hld(edges[i].u, edges[i].v, 1); } for(int mid = 0; mid <= m; ++mid) { if (mid > 0) { hld1.update_hld(edges[mid].u, edges[mid].v, edges[mid].cost); hld2.update_hld(edges[mid].u, edges[mid].v, -1); } for(auto _ : queries[mid]) { int s = eq[_].s; int t = eq[_].t; int x = eq[_].x; ll y = eq[_].y; int id = eq[_].id; ll silver = hld1.query_hld(s, t); int gold = hld2.query_hld(s, t); if (silver <= y) { ANS[id] = max(ANS[id], x - gold); L[_] = mid + 1; } else { R[_] = mid - 1; } } queries[mid].clear(); } hld1.reset(); hld2.reset(); } for(int i = 1; i <= q; ++i) { cout << ANS[i] << el; } } signed main() { ios_base::sync_with_stdio(false); cin.tie(0); #define task "task" if(fopen(task".inp", "r")) { freopen(task".inp", "r", stdin); freopen(task".out", "w", stdout); } solve(); return 0; } /* */

Compilation message (stderr)

currencies.cpp: In function 'int main()':
currencies.cpp:320:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  320 |         freopen(task".inp", "r", stdin);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
currencies.cpp:321:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  321 |         freopen(task".out", "w", stdout);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...