Submission #1293384

#TimeUsernameProblemLanguageResultExecution timeMemory
1293384fishy15Dynamic Diameter (CEOI19_diameter)C++20
100 / 100
4556 ms253344 KiB
#include <iostream> #include <iomanip> #include <fstream> #include <vector> #include <array> #include <algorithm> #include <utility> #include <map> #include <queue> #include <set> #include <cmath> #include <cstdio> #include <cstring> #include <functional> #include <numeric> #define ll long long #define ld long double #define eps 1e-8 #define MOD 1000000007 #define INF 0x3f3f3f3f #define INFLL 0x3f3f3f3f3f3f3f3f #define rep(i, a, b) for(int i = a; i < (b); ++i) #define all(x) begin(x), end(x) #define sz(x) (int)(x).size() using namespace std; struct lazy_segtree { int n; mutable vector<ll> st; mutable vector<ll> lazy; lazy_segtree() : lazy_segtree(0) {} lazy_segtree(int n) : n(n), st(4 * n), lazy(4 * n) {} void push(int v, int l, int r) const { if (r - l != 1) { lazy[2 * v] += lazy[v]; lazy[2 * v + 1] += lazy[v]; } st[v] += lazy[v]; lazy[v] = 0; } void upd(int x, int y, ll q) { upd(x, y, q, 1, 0, n); } void upd(int x, int y, ll q, int v, int l, int r) { push(v, l, r); if (r <= x || l >= y) return; if (x <= l && r <= y) { lazy[v] += q; push(v, l, r); } else { int m = (l + r) / 2; upd(x, y, q, 2 * v, l, m); upd(x, y, q, 2 * v + 1, m, r); st[v] = max(st[2 * v], st[2 * v + 1]); } } ll qry(int x, int y) const { return qry(x, y, 1, 0, n); } ll qry(int x, int y, int v, int l, int r) const { push(v, l, r); if (r <= x || l >= y) return 0; if (x <= l && r <= y) return st[v]; int m = (l + r) / 2; return max(qry(x, y, 2 * v, l, m), qry(x, y, 2 * v + 1, m, r)); } }; struct CD { vector<vector<pair<int, ll>>> adj; vector<int> size, vis; vector<vector<int>> pars; // parents in centroid tree vector<map<int, int>> in; vector<vector<int>> out; vector<vector<int>> orig; vector<multiset<ll, greater<>>> best_branches; vector<lazy_segtree> segtrees; multiset<ll, greater<>> centroid_ans; CD(int n) : adj(n), size(n), vis(n), pars(n), in(n), out(n), orig(n), best_branches(n), segtrees(n) {} void add_edge(int u, int v, ll w) { adj[u].push_back({v, w}); adj[v].push_back({u, w}); } int dfs_size(int v, int p) { size[v] = 1; for (auto [e, _] : adj[v]) { if (e != p && !vis[e]) { size[v] += dfs_size(e, v); } } return size[v]; } int dfs_root(int v, int p, int n) { for (auto [e, _] : adj[v]) { if (e != p && !vis[e] && 2 * size[e] > n) { return dfs_root(e, v, n); } } return v; } void dfs_build(int v, int p, int c, int orig, int &t, ll up_w) { auto idx = in[c][v] = t++; pars[v].push_back(c); this->orig[c][idx] = orig; for (auto [e, w] : adj[v]) { if (!vis[e] && e != p) { dfs_build(e, v, c, orig, t, w); } } out[c][idx] = t; segtrees[c].upd(idx, t, up_w); // if we are the start of a branch, add ourself to best branches set if (v == orig) { best_branches[c].insert(segtrees[c].qry(idx, t)); } } void build(int c, int size) { out[c].resize(size); orig[c].resize(size); segtrees[c] = lazy_segtree(size); int t = 0; in[c][c] = t++; pars[c].push_back(c); orig[c][0] = -1; for (auto [e, w] : adj[c]) { if (!vis[e]) { dfs_build(e, c, c, e, t, w); } } out[c][0] = t; centroid_ans.insert(get_ans(c)); } ll get_ans(int c) { if (sz(best_branches[c]) == 0) { return 0; } else if (sz(best_branches[c]) == 1) { return *begin(best_branches[c]); } else { return *begin(best_branches[c]) + *next(begin(best_branches[c])); } } void centroid(int v, int p) { int comp_size = dfs_size(v, p); int c = dfs_root(v, p, size[v]); build(c, comp_size); vis[c] = true; for (auto [e, _] : adj[c]) { if (!vis[e]) { centroid(e, c); } } } void upd_in_c(int c, int u, int v, ll diff) { int in_idx = max(in[c][u], in[c][v]); int out_idx = out[c][in_idx]; int orig = this->orig[c][in_idx]; int orig_in = in[c][orig]; int orig_out = out[c][orig_in]; centroid_ans.erase(centroid_ans.find(get_ans(c))); best_branches[c].erase(best_branches[c].find(segtrees[c].qry(orig_in, orig_out))); segtrees[c].upd(in_idx, out_idx, diff); best_branches[c].insert(segtrees[c].qry(orig_in, orig_out)); centroid_ans.insert(get_ans(c)); } void upd_weight(int u, int v, ll diff) { for (auto c : pars[u]) { if (in[c].count(v)) { upd_in_c(c, u, v, diff); } } } }; int main() { cin.tie(0)->sync_with_stdio(0); int n, q; ll W; cin >> n >> q >> W; CD tree(n); vector<array<ll, 3>> edges; rep(i, 0, n-1) { int u, v; ll w; cin >> u >> v >> w; u--; v--; tree.add_edge(u, v, w); edges.push_back({u, v, w}); } tree.centroid(0, 0); ll last = 0; while (q--) { ll dp, ep; cin >> dp >> ep; auto idx = (dp + last) % (n - 1); auto [u, v, cur_w] = edges[idx]; auto new_w = (ep + last) % W; tree.upd_weight(u, v, new_w - cur_w); edges[idx][2] = new_w; last = *begin(tree.centroid_ans); cout << last << '\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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...