This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#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(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;
std::vector<int> revIn;
std::vector<i64> depth;
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);
int id = 0;
for (const int v : roots) {
dfs1(v, -1);
// int x = findCentroid(v, -1, size[v]);
int x = 0;
dfs2(x, -1, id, 0, -1);
}
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) {
fe[v] = f;
in[v] = id++;
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));
}
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]});
}
// subtask 5
TreeManager mng(tree, std::vector<bool>(N, true), {0});
std::vector<std::pair<i64, int>> weighVec(N);
for (int i = 0; i < N; ++i) {
weighVec[mng.in[i]].first = mng.depth[i];
}
for (int i = 0; i < N; ++i) {
weighVec[i].second = i;
}
lazySegtree seg(weighVec);
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];
if (mng.depth[a] > mng.depth[b]) std::swap(a, b);
// b
seg.apply(mng.in[b], mng.out[b], (w - C[i]));
C[i] = w;
const auto [v, p] = seg.fold(0, N);
const int l = mng.in[mng.fe[mng.revIn[p]]], r = mng.out[mng.fe[mng.revIn[p]]];
const auto v2 = std::max(seg.fold(0, l).first, seg.fold(r, N).first);
last = v + v2;
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... |