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

#TimeUsernameProblemLanguageResultExecution timeMemory
703174CyanmondDynamic Diameter (CEOI19_diameter)C++17
100 / 100
4722 ms169868 KiB
#pragma GCC target("avx2") #pragma GCC optimize("O3") #include <bits/stdc++.h> using i64 = long long; struct Edge { int to; i64 w; }; using T = std::pair<i64, int>; T op(const T& a, const T& b) { return std::max(a, b); } T e() { return {0, 0}; } using U = i64; T map(i64 a, const T& b) { return {b.first + a, b.second}; } i64 composite(i64 a, i64 b) { return a + b; } i64 id() { return 0; } class lazySegtree { int n, logn, size; std::vector<T> node; std::vector<U> lazy; void update(int i) { node[i] = op(node[2 * i], node[2 * i + 1]); } void all_apply(int i, U f) { node[i] = map(f, node[i]); if (i < size) lazy[i] = composite(f, lazy[i]); } void push(int i) { all_apply(2 * i, lazy[i]); all_apply(2 * i + 1, lazy[i]); lazy[i] = id(); } public: lazySegtree() {} lazySegtree(std::vector<T> initVec) { n = (int)initVec.size(); logn = 0; while ((1 << logn) < n) { ++logn; } size = 1 << logn; node.assign(2 * size, e()); lazy.assign(size, id()); std::copy(initVec.begin(), initVec.end(), node.begin() + size); for (int i = size - 1; i >= 1; --i) { update(i); } } void apply(int l, int r, U f) { l += size, r += size; for (int d = logn; d >= 1; --d) { if (((l >> d) << d) != l) push(l >> d); if (((r >> d) << d) != r) push((r - 1) >> d); } int l2 = l, r2 = r; while (l < r) { if (l & 1) all_apply(l++, f); if (r & 1) all_apply(--r, f); l /= 2; r /= 2; } l = l2, r = r2; for (int d = 1; d <= logn; ++d) { if (((l >> d) << d) != l) update(l >> d); if (((r >> d) << d) != r) update((r - 1) >> d); } } T fold(int l, int r) { l += size, r += size; for (int d = logn; d >= 1; --d) { if (((l >> d) << d) != l) push(l >> d); if (((r >> d) << d) != r) push((r - 1) >> d); } T pl = e(), pr = e(); while (l < r) { if (l & 1) pl = op(pl, node[l++]); if (r & 1) pr = op(node[--r], pr); l /= 2; r /= 2; } return op(pl, pr); } }; std::vector<std::vector<Edge>> tree; struct TreeManager { int n; std::vector<char> isOn, isCentroid; std::vector<int> size, in, out, fe, cen; std::vector<int> revIn; std::vector<i64> depth; TreeManager() {} TreeManager(const std::vector<char> &ison, const std::vector<int> &roots) { isOn = ison; n = tree.size(); isCentroid.assign(n, false); size.assign(n, -1); in.assign(n, -1); out.assign(n, -1); depth.assign(n, 0); fe.assign(n, 0); cen.assign(n, 0); int id = 0; for (const int v : roots) { dfs1(v, -1); int x = findCentroid(v, -1, size[v]); dfs2(x, -1, id, 0, -1, x); } revIn.resize(n); for (int i = 0; i < n; ++i) { if (in[i] >= 0) { revIn[in[i]] = i; } } } void dfs1(int v, int p) { size[v] = 1; for (const auto &[t, w] : tree[v]) { if (t == p or (not isOn[t])) { continue; } dfs1(t, v); size[v] += size[t]; } } int findCentroid(int v, int p, int as) { bool isCent = true; for (const auto &[t, w] : tree[v]) { if (t == p or (not isOn[t])) { continue; } int res = findCentroid(t, v, as); if (res != -1) { return res; } if (size[t] > as / 2) { isCent = false; } } if ((as - size[v]) > as / 2) { isCent = false; } isCentroid[v] = isCent; return isCent ? v : -1; } void dfs2(int v, int p, int &id, i64 d, int f, int ce) { fe[v] = f; in[v] = id++; cen[v] = ce; depth[v] = d; size[v] = 1; for (const auto &[t, w] : tree[v]) { if (t == p or (not isOn[t])) { continue; } dfs2(t, v, id, d + w, (f == -1 ? t : f), ce); size[v] += size[t]; } out[v] = id; } }; int main() { int N, Q; i64 W; std::cin >> N >> Q >> W; std::vector<int> A(N - 1), B(N - 1); std::vector<i64> C(N - 1); tree.resize(N); for (int i = 0; i < N - 1; ++i) { std::cin >> A[i] >> B[i] >> C[i]; --A[i], --B[i]; tree[A[i]].push_back({B[i], C[i]}); tree[B[i]].push_back({A[i], C[i]}); } std::vector<char> isOn(N, true); std::vector<int> roots = {0}; std::vector<TreeManager> managers; while (true) { TreeManager mng(isOn, roots); roots.clear(); for (int i = 0; i < N; ++i) { if (not mng.isCentroid[i]) { continue; } isOn[i] = false; for (const auto &[t, w] : tree[i]) { if (not isOn[t]) { continue; } roots.push_back(t); } } managers.push_back(std::move(mng)); if (std::none_of(isOn.begin(), isOn.end(), [](bool b) { return b; })) { break; } } const int m = (int)managers.size(); std::vector<lazySegtree> segs(m); std::multiset<i64> diameters; std::vector<i64> memoDiameters(N); for (int x = 0; x < m; ++x) { auto &mng = managers[x]; std::vector<std::pair<i64, int>> weighVec(N); for (int i = 0; i < N; ++i) { if (mng.in[i] == -1) { continue; } weighVec[mng.in[i]].first = mng.depth[i]; } for (int i = 0; i < N; ++i) { weighVec[i].second = i; } segs[x] = lazySegtree(weighVec); for (int i = 0; i < N; ++i) { if (not mng.isCentroid[i]) { continue; } if (mng.size[i] == 1) { continue; } const int bl = mng.in[i], br = mng.out[i]; const auto [v, p] = segs[x].fold(bl, br); const int l = mng.in[mng.fe[mng.revIn[p]]], r = mng.out[mng.fe[mng.revIn[p]]]; const auto v2 = std::max(segs[x].fold(bl, l).first, segs[x].fold(r, br).first); diameters.insert(v + v2); memoDiameters[i] = v + v2; } } i64 last = 0; while (Q--) { int d; i64 e; std::cin >> d >> e; i64 i = (last + d) % (N - 1); i64 w = (last + e) % W; int a = A[i], b = B[i]; for (int x = 0; x < m; ++x) { auto &mng = managers[x]; if ((not mng.isOn[a]) or (not mng.isOn[b])) { break; } if (mng.depth[a] > mng.depth[b]) { std::swap(a, b); } const int c = mng.cen[a]; if (mng.size[c] == 1) { break; } diameters.erase(diameters.find(memoDiameters[c])); segs[x].apply(mng.in[b], mng.out[b], (w - C[i])); const int bl = mng.in[c], br = mng.out[c]; const auto [v3, p3] = segs[x].fold(bl, br); const int l = mng.in[mng.fe[mng.revIn[p3]]], r = mng.out[mng.fe[mng.revIn[p3]]]; const auto v2 = std::max(segs[x].fold(bl, l).first, segs[x].fold(r, br).first); diameters.insert(v3 + v2); memoDiameters[c] = v3 + v2; } C[i] = w; last = *diameters.rbegin(); std::cout << last << std::endl; } }
#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...