제출 #1279640

#제출 시각아이디문제언어결과실행 시간메모리
1279640LIADynamic Diameter (CEOI19_diameter)C++17
11 / 100
5096 ms1114112 KiB
#include <bits/stdc++.h> using namespace std; #define ll long long #define f first #define s second const ll inf = 1e18; #define vll vector<ll> ll n, q, w; vector<tuple<ll, ll, ll>> edges; vector<ll> tin, tout, par, comp, vin; ll timer = 0; vector<vector<ll>> g; void dfs(ll node, ll pari) { par[node] = pari; tin[node] = timer++; vin[tin[node]] = node; for (auto it : g[node]) { if (it == pari) continue; dfs(it, node); } tout[node] = timer - 1; } void dfs2(ll node, ll pari, ll id) { comp[node] = id; for (auto it : g[node]) { if (it == pari) continue; dfs2(it, node, node == 0 ? it : id); } } struct cand { ll val; ll id; }; struct node { cand a, b; ll lazy; }; node merge(node A, node B) { vector<cand> v = {A.a, A.b, B.a, B.b}; sort(v.begin(), v.end(), [](cand x, cand y) { return x.val > y.val; }); node res; res.a = v[0]; res.b = {-(ll)4e18, -1}; for (auto x : v) if (x.id != res.a.id) { res.b = x; break; } res.lazy = 0; return res; } struct Seg { vector<node> seg; ll sz = 1; Seg() { tin.resize(n), tout.resize(n), par.resize(n), comp.resize(n), vin.resize(n); timer = 0; dfs(0, -1); dfs2(0, -1, -1); for (; sz < n; sz *= 2) ; seg.resize(2 * sz); for (ll i = 0; i < n; i++) { ll v = vin[i]; seg[sz + i].a = {0, comp[v]}; seg[sz + i].b = {-(ll)4e18, -1}; } for (ll i = sz - 1; i >= 1; --i) seg[i] = merge(seg[i * 2], seg[i * 2 + 1]); } void push(ll i) { ll x = seg[i].lazy; if (x == 0) return; seg[i * 2].a.val += x; seg[i * 2].b.val += x; seg[i * 2].lazy += x; seg[i * 2 + 1].a.val += x; seg[i * 2 + 1].b.val += x; seg[i * 2 + 1].lazy += x; seg[i].lazy = 0; } void update(ll i, ll l, ll r, ll a, ll b, ll w) { if (l > b || r < a) return; if (l >= a && r <= b) { seg[i].a.val += w; seg[i].b.val += w; seg[i].lazy += w; return; } push(i); ll mid = (l + r) / 2; update(i * 2, l, mid, a, b, w); update(i * 2 + 1, mid + 1, r, a, b, w); seg[i] = merge(seg[i * 2], seg[i * 2 + 1]); } void update(ll node, ll w) { ll l = tin[node], r = tout[node]; update(1, 0, sz - 1, l, r, w); } ll ans() { return seg[1].a.val + seg[1].b.val; } }; vector<vector<pair<ll, ll>>> wg; vector<vector<pair<ll, ll>>> adj_e; vector<ll> deadc, szt; ll Nsz; void getsz(ll u, ll p) { szt[u] = 1; for (auto [v, id] : adj_e[u]) { if (v == p || deadc[v]) continue; getsz(v, u); szt[u] += szt[v]; } } ll getcent(ll u, ll p, ll tot) { for (auto [v, id] : adj_e[u]) { if (v == p || deadc[v]) continue; if (szt[v] * 2 > tot) return getcent(v, u, tot); } return u; } void collect_nodes(ll u, ll p, vector<ll>& vec) { vec.push_back(u); for (auto [v, id] : adj_e[u]) { if (v == p || deadc[v]) continue; collect_nodes(v, u, vec); } } struct SegC { vector<node> seg; ll sz = 1; vector<ll> alive; vector<ll> compc; ll c; SegC(ll cc, const vector<ll>& nodes) { c = cc; for (; sz < n; sz *= 2) ; seg.resize(2 * sz); alive.assign(n, 0); compc.assign(n, -1); for (auto v : nodes) alive[v] = 1; vector<ll> dist(n, 0); deque<ll> dq; dq.push_back(c); vector<ll> vis(n, 0); vis[c] = 1; while (!dq.empty()) { ll u = dq.front(); dq.pop_front(); for (auto [v, id] : wg[u]) { if (vis[v] || deadc[v]) continue; vis[v] = 1; dist[v] = dist[u] + get<2>(edges[id]); dq.push_back(v); } } function<void(ll, ll, ll)> dfscomp = [&](ll u, ll p, ll id) { compc[u] = id; for (auto [v, eid] : adj_e[u]) { if (v == p || deadc[v]) continue; dfscomp(v, u, u == c ? v : id); } }; dfscomp(c, -1, -1); for (ll i = 0; i < n; ++i) { ll v = vin[i]; if (alive[v]) { seg[sz + i].a = {dist[v], compc[v]}; } else { seg[sz + i].a = {-(ll)4e18, -1}; } seg[sz + i].b = {-(ll)4e18, -1}; } for (ll i = sz - 1; i >= 1; --i) seg[i] = merge(seg[i * 2], seg[i * 2 + 1]); } void push(ll i) { ll x = seg[i].lazy; if (x == 0) return; seg[i * 2].a.val += x; seg[i * 2].b.val += x; seg[i * 2].lazy += x; seg[i * 2 + 1].a.val += x; seg[i * 2 + 1].b.val += x; seg[i * 2 + 1].lazy += x; seg[i].lazy = 0; } void upd(ll i, ll l, ll r, ll a, ll b, ll w) { if (l > b || r < a) return; if (l >= a && r <= b) { seg[i].a.val += w; seg[i].b.val += w; seg[i].lazy += w; return; } push(i); ll mid = (l + r) / 2; upd(i * 2, l, mid, a, b, w); upd(i * 2 + 1, mid + 1, r, a, b, w); seg[i] = merge(seg[i * 2], seg[i * 2 + 1]); } void update_range(ll l, ll r, ll w) { if (l <= r) upd(1, 0, sz - 1, l, r, w); } void update_all(ll w) { upd(1, 0, sz - 1, 0, sz - 1, w); } ll ans() { return seg[1].a.val + seg[1].b.val; } }; vector<SegC> segsC; vector<ll> cent_node; vector<ll> cent_id_of_node; vector<vector<pair<ll, ll>>> affect; ll build_centroid(ll root) { getsz(root, -1); ll c = getcent(root, -1, szt[root]); vector<ll> nodes; collect_nodes(c, -1, nodes); ll idx = (ll)segsC.size(); cent_node.push_back(c); cent_id_of_node[c] = idx; segsC.emplace_back(SegC(c, nodes)); deadc[c] = 1; for (auto [v, id] : adj_e[c]) { if (deadc[v]) continue; build_centroid(v); } return idx; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cin >> n >> q >> w; edges.resize(n - 1); g.resize(n); wg.assign(n, {}); adj_e.assign(n, {}); for (ll i = 0; i < n - 1; ++i) { ll a, b, c; cin >> a >> b >> c; a--; b--; edges[i] = {a, b, c}; g[a].push_back(b); g[b].push_back(a); } Seg seg; par[0] = -1; for (ll i = 0; i < n - 1; ++i) { auto& [a, b, c] = edges[i]; if (par[b] != a) swap(a, b); seg.update(b, c); } wg.clear(); wg.assign(n, {}); adj_e.assign(n, {}); for (ll i = 0; i < n - 1; ++i) { auto [a, b, c] = edges[i]; wg[a].push_back({b, i}); wg[b].push_back({a, i}); adj_e[a].push_back({b, i}); adj_e[b].push_back({a, i}); } deadc.assign(n, 0); szt.assign(n, 0); cent_id_of_node.assign(n, -1); affect.assign(n - 1, {}); build_centroid(0); for (ll ci = 0; ci < (ll)segsC.size(); ++ci) { ll c = cent_node[ci]; for (ll i = 0; i < n - 1; ++i) { auto [a, b, wc] = edges[i]; ll inside = (tin[c] >= tin[b] && tin[c] <= tout[b]) ? 1 : 0; affect[i].push_back({ci, inside}); } } multiset<ll> ms; vector<ll> cur(segsC.size()); for (ll i = 0; i < (ll)segsC.size(); ++i) { cur[i] = segsC[i].ans(); ms.insert(cur[i]); } ll last = 0; while (q--) { ll d, e; cin >> d >> e; ll d1 = (d + last) % (n - 1); ll e1 = (e + last) % w; auto& [a, b, c] = edges[d1]; ll dis = e1 - c; c = e1; for (auto pr : affect[d1]) { ll ci = pr.f; ll inside = pr.s; ms.erase(ms.find(cur[ci])); if (inside) { segsC[ci].update_all(dis); segsC[ci].update_range(tin[b], tout[b], -dis); } else { segsC[ci].update_range(tin[b], tout[b], dis); } cur[ci] = segsC[ci].ans(); ms.insert(cur[ci]); } last = *ms.rbegin(); cout << last << endl; } }
#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...