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

#TimeUsernameProblemLanguageResultExecution timeMemory
1074107_callmelucianDynamic Diameter (CEOI19_diameter)C++14
100 / 100
2545 ms209316 KiB
#include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef pair<ll,ll> pl; typedef pair<int,int> pii; typedef tuple<int,int,ll> tt; #define all(a) a.begin(), a.end() #define filter(a) a.erase(unique(all(a)), a.end()) const int mn = 1e5 + 5; const int LOG = 19; struct IT { vector<pl> tr; IT() {} IT (int sz) : tr(4 * sz) {} void update (int pos, ll val, int k, int l, int r) { if (pos < l || r < pos) return; if (l == r) { tr[k] = {val, l}; return; } int mid = (l + r) >> 1; update(pos, val, 2 * k, l, mid); update(pos, val, 2 * k + 1, mid + 1, r); tr[k] = max(tr[2 * k], tr[2 * k + 1]); } pl query (int a, int b, int k, int l, int r) { if (b < l || r < a) return {0, 0}; if (a <= l && r <= b) return tr[k]; int mid = (l + r) >> 1; return max(query(a, b, 2 * k, l, mid), query(a, b, 2 * k + 1, mid + 1, r)); } } tree[mn], childDiam[mn]; struct lazyIT { vector<ll> tr, lazy; lazyIT() {} lazyIT (int sz) : tr(4 * sz), lazy(4 * sz) {} ll get (int k) { return tr[k] + lazy[k]; } void pushDown (int k) { lazy[2 * k] += lazy[k], lazy[2 * k + 1] += lazy[k], lazy[k] = 0; tr[k] = max(get(2 * k), get(2 * k + 1)); } void update (int a, int b, ll inc, int k, int l, int r) { if (b < l || r < a) return; if (a <= l && r <= b) { lazy[k] += inc; return; } pushDown(k); int mid = (l + r) >> 1; update(a, b, inc, 2 * k, l, mid); update(a, b, inc, 2 * k + 1, mid + 1, r); tr[k] = max(get(2 * k), get(2 * k + 1)); } ll query (int a, int b, int k, int l, int r) { if (b < l || r < a) return 0; if (a <= l && r <= b) return get(k); pushDown(k); int mid = (l + r) >> 1; return max(query(a, b, 2 * k, l, mid), query(a, b, 2 * k + 1, mid + 1, r)); } } depth[mn]; ll in[LOG][mn], out[LOG][mn], ctroid[LOG][mn]; ll diameter[mn], sz[mn], sztr[mn], timeDfs; vector<int> child[mn]; vector<pl> adj[mn]; bool del[mn]; void calcDfs (int u, int p, int root, int layer) { in[layer][u] = ++timeDfs; for (auto [v, w] : adj[u]) { if (del[v] || v == p) continue; calcDfs(v, u, root, layer); depth[root].update(in[layer][v], out[layer][v], w, 1, 1, sztr[root]); } out[layer][u] = timeDfs; } int szDfs (int u, int p) { sz[u] = 1; for (auto [v, w] : adj[u]) if (!del[v] && v != p) sz[u] += szDfs(v, u); return sz[u]; } int centroid (int u, int p, int layer, int cursz) { for (auto [v, w] : adj[u]) if (!del[v] && v != p && sz[v] > cursz / 2) return centroid(v, u, layer, cursz); return u; } ll twoBest (IT &tr, int sz) { ll best, pos; tie(best, pos) = tr.query(0, sz, 1, 0, sz); tr.update(pos, 0, 1, 0, sz); ll sec = tr.query(0, sz, 1, 0, sz).first; tr.update(pos, best, 1, 0, sz); return best + sec; } ll getDiam (int layer, int u) { return diameter[ctroid[layer][u]]; } void preDfs (int u, int layer) { szDfs(u, u); int tmp = sz[u], ori = u; u = ctroid[layer][u] = centroid(u, u, layer, tmp); sztr[u] = tmp, depth[u] = lazyIT(tmp), tree[u] = IT(adj[u].size()), childDiam[u] = IT(adj[u].size()); timeDfs = 0, calcDfs(u, u, u, layer), del[u] = 1; int trsz = adj[u].size() - 1; for (int i = 0; i < adj[u].size(); i++) { ll v, w; tie(v, w) = adj[u][i]; if (del[v]) continue; preDfs(v, layer + 1); ll cur = depth[u].query(in[layer][v], out[layer][v], 1, 1, sztr[u]); tree[u].update(child[u].size(), cur, 1, 0, trsz); childDiam[u].update(child[u].size(), getDiam(layer + 1, v), 1, 0, trsz); child[u].push_back(v); } diameter[u] = max(childDiam[u].query(0, trsz, 1, 0, trsz).first, twoBest(tree[u], trsz)); del[u] = 0; } void update (int u, int layer, int a, int b, ll incr) { int ori = u; u = ctroid[layer][u], del[u] = 1; if (depth[u].query(in[layer][a], in[layer][a], 1, 1, sztr[u]) > depth[u].query(in[layer][b], in[layer][b], 1, 1, sztr[u])) swap(a, b); // for this re-rooted subtree, a is parent of b depth[u].update(in[layer][b], out[layer][b], incr, 1, 1, sztr[u]); int trsz = adj[u].size() - 1; function<bool(int,int,int)> range = [&] (int p, int l, int r) { return l <= p && p <= r; }; function<bool(int,int)> cmp = [&] (int a, int b) { return in[layer][a] < in[layer][b]; }; int id = upper_bound(all(child[u]), b, cmp) - child[u].begin() - 1, v = child[u][id]; ll cur = depth[u].query(in[layer][v], out[layer][v], 1, 1, sztr[u]); tree[u].update(id, cur, 1, 0, trsz); if (u != a) { update(v, layer + 1, a, b, incr); childDiam[u].update(id, getDiam(layer + 1, v), 1, 0, trsz); } diameter[u] = max(childDiam[u].query(0, trsz, 1, 0, trsz).first, twoBest(tree[u], trsz)), del[u] = 0; } int main() { ios::sync_with_stdio(0); cin.tie(0); int n, q; ll w; cin >> n >> q >> w; vector<tt> edge; for (int i = 1; i < n; i++) { int a, b; ll c; cin >> a >> b >> c; adj[a].emplace_back(b, c); adj[b].emplace_back(a, c); edge.emplace_back(a, b, c); } preDfs(1, 0); ll ans = 0; while (q--) { ll x, y; cin >> x >> y; ll d = (ans + x) % (n - 1), e = (ans + y) % w; int a, b; ll weight; tie(a, b, weight) = edge[d]; ll incr = e - weight; edge[d] = make_tuple(a, b, e); update(1, 0, a, b, incr); ans = getDiam(0, 1); cout << ans << "\n"; } return 0; }

Compilation message (stderr)

diameter.cpp: In function 'void calcDfs(int, int, int, int)':
diameter.cpp:85:15: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17'
   85 |     for (auto [v, w] : adj[u]) {
      |               ^
diameter.cpp: In function 'int szDfs(int, int)':
diameter.cpp:95:15: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17'
   95 |     for (auto [v, w] : adj[u])
      |               ^
diameter.cpp: In function 'int centroid(int, int, int, int)':
diameter.cpp:101:15: warning: structured bindings only available with '-std=c++17' or '-std=gnu++17'
  101 |     for (auto [v, w] : adj[u])
      |               ^
diameter.cpp: In function 'void preDfs(int, int)':
diameter.cpp:126:23: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<long long int, long long int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  126 |     for (int i = 0; i < adj[u].size(); i++) {
      |                     ~~^~~~~~~~~~~~~~~
diameter.cpp:119:22: warning: unused variable 'ori' [-Wunused-variable]
  119 |     int tmp = sz[u], ori = u;
      |                      ^~~
diameter.cpp: In function 'void update(int, int, int, int, ll)':
diameter.cpp:142:9: warning: unused variable 'ori' [-Wunused-variable]
  142 |     int ori = u;
      |         ^~~
#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...