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

#TimeUsernameProblemLanguageResultExecution timeMemory
680085SanguineChameleonDynamic Diameter (CEOI19_diameter)C++17
100 / 100
2469 ms165328 KiB
// BEGIN BOILERPLATE CODE #include <bits/stdc++.h> using namespace std; #ifdef KAMIRULEZ const bool kami_loc = true; const long long kami_seed = 69420; #else const bool kami_loc = false; const long long kami_seed = chrono::steady_clock::now().time_since_epoch().count(); #endif const string kami_fi = "kamirulez.inp"; const string kami_fo = "kamirulez.out"; mt19937_64 kami_gen(kami_seed); long long rand_range(long long rmin, long long rmax) { uniform_int_distribution<long long> rdist(rmin, rmax); return rdist(kami_gen); } long double rand_real(long double rmin, long double rmax) { uniform_real_distribution<long double> rdist(rmin, rmax); return rdist(kami_gen); } void file_io(string fi, string fo) { if (fi != "" && (!kami_loc || fi == kami_fi)) { freopen(fi.c_str(), "r", stdin); } if (fo != "" && (!kami_loc || fo == kami_fo)) { freopen(fo.c_str(), "w", stdout); } } void set_up() { if (kami_loc) { file_io(kami_fi, kami_fo); } ios_base::sync_with_stdio(0); cin.tie(0); } void just_do_it(); void just_exec_it() { if (kami_loc) { auto pstart = chrono::steady_clock::now(); just_do_it(); auto pend = chrono::steady_clock::now(); long long ptime = chrono::duration_cast<chrono::milliseconds>(pend - pstart).count(); string bar(50, '='); cout << '\n' << bar << '\n'; cout << "Time: " << ptime << " ms" << '\n'; } else { just_do_it(); } } int main() { set_up(); just_exec_it(); return 0; } // END BOILERPLATE CODE // BEGIN MAIN CODE const int ms = 1e5 + 20; struct range { int root = 0; int pos = 0; int lt = 0; int rt = 0; range() { } range(int _root, int _pos, int _lt, int _rt) { root = _root; pos = _pos; lt = _lt; rt = _rt; } }; long long a[ms]; struct tree { vector<long long> tr; vector<long long> lz; int n = 0; void build(int cc, int lt, int rt) { if (lt == rt) { tr[cc] = a[lt]; return; } int mt = (lt + rt) / 2; build(cc << 1, lt, mt); build(cc << 1 | 1, mt + 1, rt); tr[cc] = max(tr[cc << 1], tr[cc << 1 | 1]); } tree() { } tree(int _n) { n = _n; tr.resize(n << 2); lz.resize(n << 2); build(1, 1, n); } void push(int cc) { tr[cc << 1] += lz[cc]; lz[cc << 1] += lz[cc]; tr[cc << 1 | 1] += lz[cc]; lz[cc << 1 | 1] += lz[cc]; lz[cc] = 0; } void update(int cc, int lt, int rt, int ql, int qr, long long pp) { if (lt == ql && rt == qr) { tr[cc] += pp; lz[cc] += pp; return; } push(cc); int mt = (lt + rt) / 2; if (qr <= mt) { update(cc << 1, lt, mt, ql, qr, pp); } else if (ql >= mt + 1) { update(cc << 1 | 1, mt + 1, rt, ql, qr, pp); } else { update(cc << 1, lt, mt, ql, mt, pp); update(cc << 1 | 1, mt + 1, rt, mt + 1, qr, pp); } tr[cc] = max(tr[cc << 1], tr[cc << 1 | 1]); } }; bool f[ms]; int sz[ms]; long long W[ms]; vector<pair<int, int>> adj[ms]; int pt[ms][2]; int tz; multiset<long long, greater<long long>> S; multiset<long long, greater<long long>> best[ms]; vector<range> R[ms]; vector<tree> T[ms]; void dfs1(int u, int pr) { sz[u] = 1; for (auto x: adj[u]) { int v = x.first; if (!f[v] && v != pr) { dfs1(v, u); sz[u] += sz[v]; } } } int ctr(int u, int pr, int root) { for (auto x: adj[u]) { int v = x.first; if (!f[v] && v != pr) { if (sz[v] * 2 > sz[root]) { return ctr(v, u, root); } } } return u; } void dfs2(int u, int pr, int root, int pos, long long cur) { tz++; pt[u][0] = tz; a[tz] = cur; sz[u] = 1; for (auto x: adj[u]) { int v = x.first; int id = x.second; if (!f[v] && v != pr) { dfs2(v, u, root, pos, cur + W[id]); R[id].emplace_back(root, pos, pt[v][0], pt[v][1]); sz[u] += sz[v]; } } pt[u][1] = tz; } long long get(int u) { long long res = 0; auto it = best[u].begin(); if (it == best[u].end()) { return res; } res += (*it); it++; if (it == best[u].end()) { return res; } res += (*it); return res; } void build(int u) { dfs1(u, -1); u = ctr(u, -1, u); f[u] = true; int cnt = 0; for (auto x: adj[u]) { int v = x.first; int id = x.second; if (!f[v]) { tz = 0; dfs2(v, -1, u, cnt, W[id]); R[id].emplace_back(u, cnt, pt[v][0], pt[v][1]); T[u].emplace_back(sz[v]); best[u].insert(T[u][cnt].tr[1]); cnt++; } } S.insert(get(u)); for (auto x: adj[u]) { int v = x.first; if (!f[v]) { build(v); } } } void update(range r, long long pp) { int root = r.root; int pos = r.pos; int lt = r.lt; int rt = r.rt; S.erase(S.find(get(root))); tree &t = T[root][pos]; best[root].erase(best[root].find(t.tr[1])); t.update(1, 1, t.n, lt, rt, pp); best[root].insert(t.tr[1]); S.insert(get(root)); } void just_do_it() { int n, q; long long lim; cin >> n >> q >> lim; for (int i = 0; i < n - 1; i++) { int u, v; cin >> u >> v >> W[i]; adj[u].emplace_back(v, i); adj[v].emplace_back(u, i); } build(1); long long res = 0; for (int i = 0; i < q; i++) { int id; long long w; cin >> id >> w; id = (res + id) % (n - 1); w = (res + w) % lim; for (auto r: R[id]) { update(r, w - W[id]); } W[id] = w; res = *S.begin(); cout << res << '\n'; } } // END MAIN CODE

Compilation message (stderr)

diameter.cpp: In function 'void file_io(std::string, std::string)':
diameter.cpp:30:10: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
   30 |   freopen(fi.c_str(), "r", stdin);
      |   ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
diameter.cpp:33:10: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
   33 |   freopen(fo.c_str(), "w", stdout);
      |   ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
#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...