(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 #619341

#TimeUsernameProblemLanguageResultExecution timeMemory
619341maximath_1Dynamic Diameter (CEOI19_diameter)C++11
100 / 100
4670 ms108056 KiB
#include <bits/stdc++.h> #pragma GCC optimize("O3", "unroll-loops") using namespace std; #define ll long long const int MX = 1e5 + 69; const int LG = 17; const ll inf = 4e18 + 69; #define ll long long int n, q; ll wtwtwt; vector<pair<pair<int, int>, ll> > edges; vector<int> adj[MX]; struct SegmentTree{ ll st[MX * 2], lz[MX * 2]; #define cm (cl + cr) / 2 #define lc nd + 1 #define rc nd + 2 * (cm - cl + 1) inline void prop(int nd, int cl, int cr){ if(lz[nd]){ st[nd] += lz[nd]; if(cl != cr){ lz[lc] += lz[nd]; lz[rc] += lz[nd]; } lz[nd] = 0; } } inline void upd(int nd, int cl, int cr, int lf, int rg, ll vl){ prop(nd, cl, cr); if(cr < lf || rg < cl) return; if(lf <= cl && cr <= rg){ lz[nd] += vl; prop(nd, cl, cr); return; } upd(lc, cl, cm, lf, rg, vl); upd(rc, cm + 1, cr, lf, rg, vl); st[nd] = max(st[lc], st[rc]); } inline ll que(int nd, int cl, int cr, int lf, int rg){ prop(nd, cl, cr); if(cr < lf || rg < cl) return -1; if(lf <= cl && cr <= rg) return st[nd]; ll L = que(lc, cl, cm, lf, rg); ll R = que(rc, cm + 1, cr, lf, rg); return max(L, R); } } st[LG]; struct SegmentTreeIterative{ ll st[MX << 1]; inline void upd(int ps, ll vl){ for(ps += MX, st[ps] = vl, ps >>= 1; ps > 0; ps >>= 1) st[ps] = max(st[ps << 1], st[ps << 1 | 1]); } inline ll que(ll lf, ll rg){ ll rs = 0ll; for(lf += MX, rg += MX + 1; lf < rg; lf >>= 1, rg >>= 1){ if(lf & 1) rs = max(st[lf ++], rs); if(rg & 1) rs = max(rs, st[-- rg]); } return rs; } } stdp; bool vis[MX], dead[MX]; int sz[MX]; inline void dfssz(int nw, int bf){ sz[nw] = 1; for(int nx : adj[nw]) if(nx != bf && !dead[nx]){ dfssz(nx, nw); sz[nw] += sz[nx]; } } int cent = -1, ccsz = 0; inline void dfscent(int nw, int bf){ for(int nx : adj[nw]) if(nx != bf && !dead[nx]) dfscent(nx, nw); if(cent == -1 && sz[nw] >= (ccsz + 1) / 2) cent = nw; } int layer = 0, tin[MX][LG], tim[LG], tout[MX][LG], rt[MX][LG], par[MX][LG], layer_id[MX]; inline void init(int nw, int bf){ rt[nw][layer] = cent; tin[nw][layer] = ++ tim[layer]; par[nw][layer] = bf; for(int nx : adj[nw]) if(nx != bf && !dead[nx]) init(nx, nw); tout[nw][layer] = tim[layer]; } vector<pair<int, int> > adj_root[MX]; inline void findCentroid(int nw){ dfssz(nw, 0); cent = -1, ccsz = sz[nw]; dfscent(nw, 0); init(cent, 0); layer_id[cent] = layer; for(int nx : adj[cent]) if(!dead[nx]) adj_root[cent].push_back({tin[nx][layer], nx}); sort(adj_root[cent].begin(), adj_root[cent].end()); dead[cent] = 1; for(int nx : adj[cent]) if(!dead[nx]){ layer ++; findCentroid(nx); layer --; } } set<pair<ll, int> > dp[MX]; int main(){ scanf("%d %d %lld", &n, &q, &wtwtwt); for(int i = 1; i < n; i ++){ int u, v; ll w; scanf("%d %d %lld", &u, &v, &w); adj[u].push_back(v); adj[v].push_back(u); edges.push_back({{u, v}, w}); } findCentroid(1); for(auto e : edges){ int u = e.first.first, v = e.first.second; ll w = e.second; for(int j = 0; j < LG; j ++){ if(rt[u][j] != rt[v][j]) break; if(tin[u][j] < tin[v][j]) swap(u, v); st[j].upd(1, 1, n, tin[u][j], tout[u][j], w); } } for(int i = 1; i <= n; i ++){ for(pair<int, int> nx : adj_root[i]) dp[i].insert({st[layer_id[i]].que(1, 1, n, tin[nx.second][layer_id[i]], tout[nx.second][layer_id[i]]), tin[nx.second][layer_id[i]]}); ll res = 0ll; auto it = dp[i].end(); for(int _ = 0; _ < 2; _ ++) if(it != dp[i].begin()){ it = prev(it); res += (*it).first; } stdp.upd(i, res); } ll last_answer = 0ll; for(; q --;){ int ee; ll wt; scanf("%d %lld", &ee, &wt); ee = (int)((ee + last_answer) % (n - 1)); wt = (wt + last_answer) % wtwtwt; int u = edges[ee].first.first, v = edges[ee].first.second; ll wtchange = wt - edges[ee].second; for(int j = 0; j < LG; j ++){ if(rt[u][j] != rt[v][j]) break; if(tin[u][j] < tin[v][j]) swap(u, v); int uid = lower_bound(adj_root[rt[u][j]].begin(), adj_root[rt[u][j]].end(), make_pair(tin[u][j] + 1, -1)) - adj_root[rt[u][j]].begin(); int anc = adj_root[rt[u][j]][uid - 1].second; dp[rt[u][j]].erase(make_pair(st[j].que(1, 1, n, tin[anc][j], tout[anc][j]), tin[anc][j])); st[j].upd(1, 1, n, tin[u][j], tout[u][j], wtchange); dp[rt[u][j]].insert(make_pair(st[j].que(1, 1, n, tin[anc][j], tout[anc][j]), tin[anc][j])); ll res = 0ll; auto it = dp[rt[u][j]].end(); for(int _ = 0; _ < 2; _ ++) if(it != dp[rt[u][j]].begin()){ it = prev(it); res += (*it).first; } stdp.upd(rt[u][j], res); } edges[ee].second = wt; last_answer = stdp.que(1, n); printf("%lld\n", last_answer); } return 0; }

Compilation message (stderr)

diameter.cpp: In function 'int main()':
diameter.cpp:121:7: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  121 |  scanf("%d %d %lld", &n, &q, &wtwtwt);
      |  ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diameter.cpp:124:8: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  124 |   scanf("%d %d %lld", &u, &v, &w);
      |   ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
diameter.cpp:157:23: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  157 |   int ee; ll wt; scanf("%d %lld", &ee, &wt);
      |                  ~~~~~^~~~~~~~~~~~~~~~~~~~~
#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...