이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#include <bits/stdc++.h>
using i64 = long long;
struct Edge {
int to;
i64 w;
};
using T = std::pair<i64, int>;
T op(T a, T b) {
return std::max(a, b);
}
T e() {
return {0, 0};
}
using U = i64;
T map(i64 a, 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);
}
};
struct TreeManager {
int n;
std::vector<std::vector<Edge>> tree;
std::vector<bool> isOn, isCentroid;
std::vector<int> size, in, out, fe, cen;
std::vector<int> revIn;
std::vector<i64> depth;
TreeManager() {}
TreeManager(const std::vector<std::vector<Edge>> &tree_, std::vector<bool> ison, std::vector<int> roots) {
isOn = ison;
tree = tree_;
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;
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);
}
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);
std::vector<std::vector<Edge>> tree(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<bool> isOn(N, true);
std::vector<int> roots = {0};
std::vector<TreeManager> managers;
while (true) {
TreeManager mng(tree, 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;
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);
}
}
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 i = d;
// i64 w = e;
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;
}
const int bl = mng.in[c], br = mng.out[c];
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.erase(diameters.find(v + v2));
segs[x].apply(mng.in[b], mng.out[b], (w - C[i]));
const auto [v3, p3] = segs[x].fold(bl, br);
const int l2 = mng.in[mng.fe[mng.revIn[p3]]], r2 = mng.out[mng.fe[mng.revIn[p3]]];
const auto v4 = std::max(segs[x].fold(bl, l2).first, segs[x].fold(r2, br).first);
diameters.insert(v3 + v4);
}
C[i] = w;
last = *diameters.rbegin();
std::cout << last << std::endl;
}
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |