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

#TimeUsernameProblemLanguageResultExecution timeMemory
719653finn__Dynamic Diameter (CEOI19_diameter)C++17
100 / 100
3251 ms151980 KiB
#include <bits/stdc++.h> using namespace std; #pragma GCC optimize("O3,unroll-loops") #pragma GCC target("avx,avx2,sse4") template <typename T, size_t L> struct SegmentTree { T t[2 * L][2]; SegmentTree() { for (size_t i = 0; i < 2 * L; i++) { t[i][0] = numeric_limits<T>::min() / 2; t[i][1] = 0; } } void build() { for (size_t i = L - 1; i; i--) t[i][0] = max(t[2 * i][0], t[2 * i + 1][0]); } void increment(size_t i, size_t j, T x, size_t k = 1, size_t a = 0, size_t b = L) { if (b <= i || a >= j) return; if (i <= a && b <= j) { t[k][0] += x; t[k][1] += x; } else { if (t[k][1]) { t[2 * k][0] += t[k][1]; t[2 * k][1] += t[k][1]; t[2 * k + 1][0] += t[k][1]; t[2 * k + 1][1] += t[k][1]; t[k][1] = 0; } increment(i, j, x, 2 * k, a, (a + b) / 2); increment(i, j, x, 2 * k + 1, (a + b) / 2, b); t[k][0] = max(t[2 * k][0], t[2 * k + 1][0]); } } T range_max(size_t i, size_t j, size_t k = 1, size_t a = 0, size_t b = L, int64_t lbound = 0) { if (b <= i || a >= j || t[k][0] <= lbound) return numeric_limits<T>::min(); if (i <= a && b <= j) return t[k][0]; if (t[k][1]) { t[2 * k][0] += t[k][1]; t[2 * k][1] += t[k][1]; t[2 * k + 1][0] += t[k][1]; t[2 * k + 1][1] += t[k][1]; t[k][1] = 0; } lbound = max(lbound, range_max(i, j, 2 * k, a, (a + b) / 2, lbound)); lbound = max(lbound, range_max(i, j, 2 * k + 1, (a + b) / 2, b, lbound)); return lbound; } void point_update(size_t i, T x) { i += L; t[i][0] = x; while (i >>= 1) t[i][0] = max(t[2 * i][0], t[2 * i + 1][0]); } }; constexpr size_t N = 100000, K = 17; set<pair<unsigned, unsigned>> g[N]; vector<unsigned> children[N]; unsigned subtree_size[N], subtree_range[K][N][2], edge_subtree[K][N], ind[K], centroid[K][N], centroid_child[K][N], level[N]; int64_t edge_weight[N]; SegmentTree<int64_t, 1 << K> t[K]; multiset<int64_t> children_height[N]; SegmentTree<int64_t, 1 << K> longest_path; unsigned find_centroid(unsigned const u, unsigned const p, unsigned const n) { subtree_size[u] = 1; bool all_subtrees_small = 1; unsigned c = UINT_MAX; for (auto const &[v, i] : g[u]) if (v != p) { unsigned x = find_centroid(v, u, n); if (x != UINT_MAX) c = x; all_subtrees_small &= subtree_size[v] <= n / 2; subtree_size[u] += subtree_size[v]; } if (all_subtrees_small && subtree_size[u] >= n / 2) c = u; return c; } void traverse(unsigned const u, unsigned const p, unsigned const d, unsigned const c, unsigned cc, int64_t const h) { if (cc == UINT_MAX && p != UINT_MAX) cc = u; centroid_child[d][u] = cc; subtree_range[d][u][0] = ind[d]++; subtree_size[u] = 1; centroid[d][u] = c; t[d].t[(1 << K) + subtree_range[d][u][0]][0] = h; for (auto const &[v, i] : g[u]) if (v != p) { edge_subtree[d][i] = v; traverse(v, u, d, c, cc, h + edge_weight[i]); subtree_size[u] += subtree_size[v]; } subtree_range[d][u][1] = ind[d]; } void decompose(unsigned const u, unsigned const n, unsigned const d) { unsigned c = find_centroid(u, UINT_MAX, n); level[c] = d; traverse(c, UINT_MAX, d, c, UINT_MAX, 0); for (auto const &[v, i] : g[c]) { children[c].push_back(v); g[v].erase(make_pair(c, i)); decompose(v, subtree_size[v], d + 1); } g[c].clear(); } int main() { size_t n, q; int64_t w; scanf("%zu %zu %" PRId64, &n, &q, &w); for (size_t i = 0; i < n - 1; i++) { unsigned a, b; int64_t c; scanf("%u %u %" PRId64, &a, &b, &c); edge_weight[i] = c; g[a - 1].emplace(b - 1, i); g[b - 1].emplace(a - 1, i); } memset(edge_subtree, 255, sizeof edge_subtree); decompose(0, n, 0); for (size_t i = 0; i < K; i++) t[i].build(); int64_t last = 0; for (unsigned i = 0; i < n; i++) { for (unsigned const &v : children[i]) children_height[i].insert( t[level[i]].range_max(subtree_range[level[i]][v][0], subtree_range[level[i]][v][1])); children_height[i].insert(0); children_height[i].insert(0); longest_path.t[(1 << K) + i][0] = *children_height[i].rbegin() + *++children_height[i].rbegin(); } longest_path.build(); while (q--) { unsigned d; int64_t e; scanf("%u %" PRId64, &d, &e); d = (d + last) % (n - 1); e = (e + last) % w; for (size_t i = K - 2; i < K; i--) if (edge_subtree[i][d] != UINT_MAX) { unsigned const u = edge_subtree[i][d], c = centroid[i][u], cchild = centroid_child[i][u]; children_height[c].erase(children_height[c].find(t[i].range_max(subtree_range[i][cchild][0], subtree_range[i][cchild][1]))); t[i].increment(subtree_range[i][u][0], subtree_range[i][u][1], e - edge_weight[d]); children_height[c].insert(t[i].range_max(subtree_range[i][cchild][0], subtree_range[i][cchild][1])); longest_path.point_update(c, *children_height[c].rbegin() + *++children_height[c].rbegin()); } edge_weight[d] = e; last = *longest_path.t[1]; printf("%" PRId64 "\n", last); } }

Compilation message (stderr)

diameter.cpp: In function 'int main()':
diameter.cpp:150:10: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  150 |     scanf("%zu %zu %" PRId64, &n, &q, &w);
      |     ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diameter.cpp:156:14: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  156 |         scanf("%u %u %" PRId64, &a, &b, &c);
      |         ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diameter.cpp:184:14: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  184 |         scanf("%u %" PRId64, &d, &e);
      |         ~~~~~^~~~~~~~~~~~~~~~~~~~~~~
#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...