(UPD: 2024-12-04 14:48 UTC) Judge is not working due to Cloudflare incident. (URL) We can do nothing about it, sorry. After the incident is resolved, we will grade all submissions.

Submission #619073

#TimeUsernameProblemLanguageResultExecution timeMemory
619073MetalPowerDynamic Diameter (CEOI19_diameter)C++14
100 / 100
4887 ms127876 KiB
#include <bits/stdc++.h> using namespace std; #define ll long long #define pii pair<int, ll> #define pli pair<ll, ll> #define fi first #define se second const int MX = 1e5 + 10; const int LG = 17; const ll INF = 1e18 + 7; int N, Q; ll W; vector<int> adj[MX]; vector<pair<pli, ll>> edges; int sz[MX], dead[MX]; void dfs(int u, int v){ sz[u] = 1; for(int nx : adj[u]){ if(nx == v || dead[nx]) continue; dfs(nx, u); sz[u] += sz[nx]; } } int cent = -1, ccsize = 0; void dfc(int u, int v){ for(int nx : adj[u]){ if(nx == v || dead[nx]) continue; dfc(nx, u); } if(cent == -1 && sz[u] >= (ccsize + 1) / 2) cent = u; } int layer = 0, tim[LG], in[MX][LG], fn[MX][LG], root[MX][LG], par[MX][LG], lnum[MX]; // Centroid Decomposition Layer // Euler Tour (in, out) for each layer // Root (Centroid) for each layer // Parent (if Centroid is root) for each layer void init(int u, int v){ root[u][layer] = cent; par[u][layer] = v; in[u][layer] = ++tim[layer]; for(int nx : adj[u]){ if(nx == v || dead[nx]) continue; init(nx, u); } fn[u][layer] = tim[layer]; } #define psi pair<int, int> vector<psi> adt[MX]; void findCentroid(int u){ dfs(u, 0); ccsize = sz[u], cent = -1; dfc(u, 0); // cout << "Centroid is " << cent << '\n'; { init(cent, 0); lnum[cent] = layer; for(int nx : adj[cent]) if(!dead[nx]) adt[cent].push_back({in[nx][layer], nx}); sort(adt[cent].begin(), adt[cent].end()); } { dead[cent] = true; for(int nx : adj[cent]){ if(dead[nx]) continue; layer++; findCentroid(nx); layer--; } } } struct itseg{ ll st[MX << 1]; void upd(int p, ll v){ for(p += MX, st[p] = v, p >>= 1; p > 0; p >>= 1) st[p] = max(st[p << 1], st[p << 1|1]); } ll que(int l, int r){ ll res = 0; for(l += MX, r += MX + 1; l < r; l >>= 1, r >>= 1){ if(l & 1) res = max(res, st[l++]); if(r & 1) res = max(res, st[--r]); } return res; } } superseg; struct segtree{ ll st[MX << 2], lz[MX << 2]; void prop(int id, int l, int r){ if(lz[id] == 0) return; st[id] += lz[id]; if(l != r){ lz[id << 1] += lz[id]; lz[id << 1|1] += lz[id]; } lz[id] = 0; } void upd(int id, int l, int r, int from, int to, ll v){ prop(id, l, r); if(r < from || l > to) return; if(from <= l && r <= to){ lz[id] += v; prop(id, l, r); }else{ int mid = l + r >> 1; upd(id << 1, l, mid, from, to, v); upd(id << 1|1, mid + 1, r, from, to, v); st[id] = max(st[id << 1], st[id << 1|1]); } } ll query(int id, int l, int r, int from, int to){ prop(id, l, r); if(r < from || l > to) return -INF; if(from <= l && r <= to){ return st[id]; }else{ int mid = l + r >> 1; return max( query(id << 1, l, mid, from, to), query(id << 1|1, mid + 1, r, from, to) ); } } } seg[LG]; set<pli> dep[MX]; // vector<int> adt[MX]; int main(){ ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin >> N >> Q >> W; for(int i = 1; i < N; i++){ int u, v; ll w; cin >> u >> v >> w; adj[u].push_back(v); adj[v].push_back(u); edges.push_back({{u, v}, w}); } // cout << "find Centroid" << '\n'; findCentroid(1); for(auto x : edges){ int u = x.fi.fi, v = x.fi.se; ll w = x.se; for(int j = 0; j < LG; j++){ if(root[u][j] != root[v][j]) break; if(in[u][j] < in[v][j]) seg[j].upd(1, 1, N, in[v][j], fn[v][j], w); else seg[j].upd(1, 1, N, in[u][j], fn[u][j], w); } } for(int i = 1; i <= N; i++){ int lyr = lnum[i]; for(psi& nx : adt[i]) dep[i].insert({seg[lyr].query(1, 1, N, in[nx.se][lyr], fn[nx.se][lyr]), in[nx.se][lyr]}); { ll ans = 0; set<pli>::iterator it = dep[i].end(); if(it != dep[i].begin()){ it--; ans += (*it).fi; } if(it != dep[i].begin()){ it--; ans += (*it).fi; } superseg.upd(i, ans); // cout << "answer for centroid " << i << " is " << ans << '\n'; } } // cout << "update depths" << '\n'; ll last = 0; for(int i = 0; i < Q; i++){ int idx; ll nw; cin >> idx >> nw; idx = (int)((last + idx) % (N - 1)); nw = (last + nw) % W; int u = edges[idx].fi.fi, v = edges[idx].fi.se; ll df = nw - edges[idx].se; // cout << "update edge " << u << " " << v << '\n'; for(int j = 0; j < LG; j++){ if(root[u][j] != root[v][j]) break; int rt = root[u][j], pnd = -1; // cout << "at layer " << j << " " << root[u][j] << '\n'; if(in[u][j] > in[v][j]){ int uid = lower_bound(adt[rt].begin(), adt[rt].end(), make_pair(in[u][j] + 1, -1)) - adt[rt].begin(); pnd = adt[rt][uid - 1].se; }else{ int uid = lower_bound(adt[rt].begin(), adt[rt].end(), make_pair(in[v][j] + 1, -1)) - adt[rt].begin(); pnd = adt[rt][uid - 1].se; } dep[rt].erase(make_pair(seg[j].query(1, 1, N, in[pnd][j], fn[pnd][j]), in[pnd][j])); if(in[u][j] < in[v][j]) seg[j].upd(1, 1, N, in[v][j], fn[v][j], df); else seg[j].upd(1, 1, N, in[u][j], fn[u][j], df); dep[rt].insert(make_pair(seg[j].query(1, 1, N, in[pnd][j], fn[pnd][j]), in[pnd][j])); { ll ans = 0; set<pli>::iterator it = dep[rt].end(); if(it != dep[rt].begin()){ it--; ans += (*it).fi; } if(it != dep[rt].begin()){ it--; ans += (*it).fi; } superseg.upd(rt, ans); } } edges[idx].se = nw; last = superseg.que(1, N); cout << last << '\n'; } }

Compilation message (stderr)

diameter.cpp: In member function 'void segtree::upd(int, int, int, int, int, long long int)':
diameter.cpp:124:16: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
  124 |    int mid = l + r >> 1;
      |              ~~^~~
diameter.cpp: In member function 'long long int segtree::query(int, int, int, int, int)':
diameter.cpp:137:16: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
  137 |    int mid = l + r >> 1;
      |              ~~^~~
#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...