#include <bits/stdc++.h> #define OnlineJudge
constexpr int N = 1e5 + 5; std::vector<int> euler_seq{-1}; int in[N], out[N], num = 0; int head[N], cnt = 0; int n, q, u, v, fa[N]; long long W, d, w, last = 0ll, dist[N]; std::vector<std::tuple<int, int, long long>> input_edges;
class Edge { public: int to, next; long long w;
} edges[N << 4];
void add_edge(int u, int v, long long w) { edges[cnt].to = v; edges[cnt].w = w; edges[cnt].next = head[u]; head[u] = cnt++; }
class SegmentTree { private: class Values { public: long long max = 0, min = 0, left_mid = 0, mid_right = 0, left_mid_right = 0, lazy = 0; }; class NodeInfo { public: int left = 0, right = 0; Values val; }; public: NodeInfo tr[N << 2]; Values merge_tags(Values a, Values b) { Values retval; retval.max = std::max(a.max, b.max); retval.min = std::min(a.min, b.min); retval.left_mid = std::max({a.left_mid, b.left_mid, a.max + -2 * b.min}); retval.mid_right = std::max({a.mid_right, b.mid_right, -2 * a.min + b.max}); retval.left_mid_right = std::max({a.left_mid_right, b.left_mid_right, a.left_mid + b.max, a.max + b.mid_right}); return retval; } void modify_tags(Values& root, long long value) { root.lazy += value; root.max += value; root.min += value; root.left_mid -= value; root.mid_right -= value; } void push_up(int k) { Values lc = tr[k << 1].val, rc = tr[k << 1 | 1].val; int temp = tr[k].val.lazy; tr[k].val = merge_tags(lc, rc); tr[k].val.lazy = temp; } void push_down(int k) { if (tr[k].val.lazy == 0) { return void(); } modify_tags(tr[k << 1].val, tr[k].val.lazy); modify_tags(tr[k << 1 | 1].val, tr[k].val.lazy); tr[k].val.lazy = 0; } void build_tree(int k, int l, int r) { tr[k].left = l; tr[k].right = r; tr[k].val.lazy = 0; if (tr[k].left == tr[k].right) { tr[k].val.max = tr[k].val.min = dist[euler_seq[l]]; tr[k].val.left_mid = tr[k].val.mid_right = -dist[euler_seq[l]]; tr[k].val.left_mid_right = 0; #ifndef OnlineJudge std::cout << "BUILD:\n"; std::cout << k << " " << tr[k].left << " " << tr[k].right << " "; std::cout << tr[k].val.max << " " << tr[k].val.min << " " << tr[k].val.left_mid << " "; std::cout << tr[k].val.mid_right << ' ' << tr[k].val.left_mid_right << " " << tr[k].val.lazy << '\n'; #endif return void(); } int mid = (tr[k].left + tr[k].right) >> 1; int lc = k << 1, rc = k << 1 | 1; build_tree(lc, l, mid); build_tree(rc, mid + 1, r); push_up(k); #ifndef OnlineJudge std::cout << "BUILD:\n"; std::cout << k << " " << tr[k].left << " " << tr[k].right << " "; std::cout << tr[k].val.max << " " << tr[k].val.min << " " << tr[k].val.left_mid << " "; std::cout << tr[k].val.mid_right << ' ' << tr[k].val.left_mid_right << " " << tr[k].val.lazy << '\n'; #endif } void modify(int k, int l, int r, long long value) { #ifndef OnlineJudge std::cout << "MODIFY:\n"; std::cout << k << " " << tr[k].left << " " << tr[k].right << " "; std::cout << tr[k].val.max << " " << tr[k].val.min << " " << tr[k].val.left_mid << " "; std::cout << tr[k].val.mid_right << ' ' << tr[k].val.left_mid_right << " " << tr[k].val.lazy << '\n'; #endif if (tr[k].left >= l && tr[k].right <= r) { modify_tags(tr[k].val, value); return void(); } push_down(k); int mid = (tr[k].left + tr[k].right) >> 1; int lc = k << 1, rc = k << 1 | 1; if (r <= mid) { modify(lc, l, r, value); } else if (l > mid) { modify(rc, l, r, value); } else { modify(lc, l, mid, value); modify(rc, mid + 1, r, value); } push_up(k); } Values query(int k, int l, int r) { #ifndef OnlineJudge std::cout << "QUERY:\n"; std::cout << k << " " << tr[k].left << " " << tr[k].right << " "; std::cout << tr[k].val.max << " " << tr[k].val.min << " " << tr[k].val.left_mid << " "; std::cout << tr[k].val.mid_right << ' ' << tr[k].val.left_mid_right << " " << tr[k].val.lazy << '\n'; #endif if (tr[k].left >= l && tr[k].right <= r) { return tr[k].val; } push_down(k); int mid = (tr[k].left + tr[k].right) >> 1; int lc = k << 1, rc = k << 1 | 1; if (r <= mid) { return query(lc, l, r); } else if (l > mid) { return query(rc, l, r); } else { return merge_tags(query(lc, l, mid), query(rc, mid + 1, r)); } } } data;
void dfs(int u, int father) { euler_seq.emplace_back(u); in[u] = euler_seq.size() - 1; for (int i = head[u]; ~i; i = edges[i].next) { int v = edges[i].to; if (v == father) continue;
fa[v] = u; dist[v] = dist[u] + edges[i].w; dfs(v, u); euler_seq.emplace_back(u); } out[u] = euler_seq.size() - 1; }
int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); std::cout.tie(nullptr); std::memset(head, -1, sizeof(head)); std::cin >> n >> q >> W; for (int i = 1; i < n; i ++) { std::cin >> u >> v >> w; add_edge(u, v, w); add_edge(v, u, w); input_edges.emplace_back(u, v, w); } dfs(1, 1); for (int i = 0; i < n - 1; i ++) { if (fa[std::get<0>(input_edges[i])] == std::get<1>(input_edges[i])) { std::swap(std::get<0>(input_edges[i]), std::get<1>(input_edges[i])); } } data.build_tree(1, 1, euler_seq.size() - 1); #ifndef OnlineJudge std::cout << data.query(1, 1, euler_seq.size() - 1).left_mid_right << '\n'; for (auto&& [u, v, w] : input_edges) { std::cout << u << ' ' << v << ' ' << w << '\n'; } #endif last = 0; for (int i = 1; i <= q; i ++) { std::cin >> d >> w; d = (d + last) % (n - 1); w = (w + last) % W; data.modify(1, in[std::get<1>(input_edges[d])], out[std::get<1>(input_edges[d])], w - std::get<2>(input_edges[d])); std::get<2>(input_edges[d]) = w; last = data.query(1, 1, euler_seq.size() - 1).left_mid_right; std::cout << last << '\n'; } return 0; }
|