Submission #1126035

#TimeUsernameProblemLanguageResultExecution timeMemory
1126035TurkhuuTwo Currencies (JOI23_currencies)C++17
100 / 100
3185 ms161384 KiB
#include <bits/stdc++.h> using namespace std; using ll = long long; struct HLD { bool e; int n, timer; vector<vector<int>> adj; vector<int> sz, dep, top, pos, par; HLD(int n, bool edge = 0) : e(edge), n(n), timer(0), adj(n), sz(n), dep(n), top(n), pos(n), par(n, -1) {} void add_edge(int x, int y) { adj[x].push_back(y); adj[y].push_back(x); } void init(int x) { sz[x] = 1; for (auto &y : adj[x]) { dep[y] = dep[x] + 1; adj[y].erase(find(adj[y].begin(), adj[y].end(), par[y] = x)); init(y); sz[x] += sz[y]; if (sz[y] > sz[adj[x][0]]) swap(y, adj[x][0]); } } void dfs(int x) { pos[x] = timer++; for (auto y : adj[x]) { top[y] = y == adj[x][0] ? top[x] : y; dfs(y); } } void build(int r = 0) { //dutuu baij magadgui timer = 0; par[r] = -1; top[r] = r; dep[r] = 0; init(r); dfs(r); } int lca(int x, int y) { for (; top[x] != top[y]; x = par[top[x]]) { if (dep[top[x]] < dep[top[y]]) swap(x, y); } return dep[x] < dep[y] ? x : y; } template<class F> int trav_path(int x, int y, F f) { for (; top[x] != top[y]; x = par[top[x]]) { if (dep[top[x]] < dep[top[y]]) swap(x, y); f(pos[top[x]], pos[x] + 1); } if (dep[x] > dep[y]) swap(x, y); f(pos[x] + e, pos[y] + 1); return x; } int operator[](int i) {return pos[i];} }; template<class S, S (*f)(S, S), S e> struct PST { struct T { T *l, *r; S s; T() : s(e) {l = r = nullptr;} T(const S &v) : s(v) {l = r = nullptr;} T(T *t) : l(t->l), r(t->r), s(t->s) {} T(T *a, T *b) : l(a), r(b), s(e) { if (l) s = f(s, l->s); if (r) s = f(s, r->s); } }; int n; vector<T*> root; PST(int m) : PST(vector<S>(m, e)) {} PST(const vector<S> &a) : n(a.size()) { function<T*(int, int)> build = [&](int l, int r) { if (l + 1 == r) return new T(a[l]); int m = (l + r) / 2; return new T(build(l, m), build(m, r)); }; root.push_back(build(0, n)); } T* upd(T *i, int l, int r, int j, const S &v, bool set) { if (l + 1 == r) return new T(set ? v : f(i->s, v)); int m = (l + r) / 2; return j < m ? new T(upd(i->l, l, m, j, v, set), i->r) : new T(i->l, upd(i->r, m, r, j, v, set)); } S qry(T *i, int l, int r, int L, int R) { if (R <= l || r <= L) return e; if (L <= l && r <= R) return i->s; int m = (l + r) / 2; return f(qry(i->l, l, m, L, R), qry(i->r, m, r, L, R)); } int last() { return root.size() - 1; } int copy(int k) { root.push_back(new T(root[k])); return root.size() - 1; } void upd(int k, int i, const S &v, bool set = 1) { root[k] = upd(root[k], 0, n, i, v, set); } S qry(int k, int l, int r) { return qry(root[k], 0, n, l, r); } }; ll f(ll a, ll b) {return a + b;} int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int N, M, Q; cin >> N >> M >> Q; HLD hld(N, 1); vector<pair<int, int>> edges(N - 1); vector<vector<pair<int, int>>> adj(N); for (int i = 0; i < N - 1; i++) { int a, b; cin >> a >> b; a--, b--; edges[i] = {a, b}; adj[a].emplace_back(b, i); adj[b].emplace_back(a, i); hld.add_edge(a, b); } vector<int> w(N - 1); { function<void(int, int)> dfs = [&](int x, int p) { for (auto [y, z] : adj[x]) { if (y == p) continue; w[z] = y; dfs(y, x); } }; dfs(0, -1); } hld.build(); vector<pair<int, int>> ch(M); for (int i = 0; i < M; i++) { int e, s; cin >> e >> s; e--; ch[i] = {s, w[e]}; } sort(ch.begin(), ch.end()); PST<ll, f, 0> pst(N); for (auto [s, i] : ch) { pst.upd(pst.copy(pst.last()), hld[i], s, 0); } vector<vector<int>> a(M + 1); vector<int> S(Q), T(Q), X(Q), ans(Q); vector<ll> Y(Q); for (int i = 0; i < Q; i++) { cin >> S[i] >> T[i] >> X[i] >> Y[i]; S[i]--, T[i]--; int lo = 0, hi = M; while (lo < hi) { int mi = (lo + hi + 1) / 2; ll s = 0; hld.trav_path(S[i], T[i], [&](int l, int r) { s += pst.qry(mi, l, r); }); s <= Y[i] ? lo = mi : hi = mi - 1; } a[lo].push_back(i); } pst = PST<ll, f, 0>(N); for (int i = M; i >= 0; i--) { if (i < M) { auto [s, j] = ch[i]; pst.upd(pst.copy(pst.last()), hld[j], 1, 0); } for (auto j : a[i]) { int cnt = 0; hld.trav_path(S[j], T[j], [&](int l, int r) { cnt += pst.qry(pst.last(), l, r); }); ans[j] = max<ll>(-1, X[j] - cnt); } } for (int i = 0; i < Q; i++) cout << ans[i] << "\n"; return 6/22; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...