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 namespace std;
const int N = 100100;
struct Edge
{
  int x, y;
  long long c;
};
struct SegmentTree
{
  int low, mid, high;
  long long v, save;
  SegmentTree *l, *r;
  SegmentTree(int low, int high, long long initialDist[]): low(low), high(high)
  {
    mid = (low + high) / 2;
    save = 0;
    if (low == high) v = initialDist[low];
    else
    {
      l = new SegmentTree(low, mid, initialDist);
      r = new SegmentTree(mid + 1, high, initialDist);
      v = max(l->v, r->v);
    }
  }
  void pushDown()
  {
    l->v += save;
    l->save += save;
    r->v += save;
    r->save += save;
    save = 0;
  }
  void update(int x, int y, long long dif)
  {
    if (low == x && high == y)
    {
      v += dif;
      save += dif;
    }
    else
    {
      pushDown();
      if (x <= mid)
        l->update(x, min(y, mid), dif);
      if (mid < y)
        r->update(max(x, mid + 1), y, dif);
      v = max(l->v, r->v);
    }
  }
  long long get(int x, int y)
  {
    if (low == x && high == y)
      return v;
    pushDown();
    long long u = 0, v = 0;
    if (x <= mid)
      u = l->get(x, min(y, mid));
    if (mid < y)
      v = r->get(max(x, mid + 1), y);
    return max(u, v);
  }
};
struct CentroidData
{
  SegmentTree *segTree;
  multiset<long long> candidates;
  vector<pair<int, int>> segments;
  long long getAns()
  {
    if (candidates.empty())
      return 0;
    auto u = candidates.rbegin();
    return candidates.size() == 1 ? *u : *u + *(++u);
  }
};
struct CentroidNode
{
  int root, preDfs, postDfs, branchId;
};
int n, dfsTime;
Edge edges[N];
vector<pair<int, int>> adj[N];
long long initialDist[N];
multiset<long long> ans;
// centroid variables
int done[N], treeSize[N];
vector<int> activeNodes;
CentroidData centroidData[N];
vector<CentroidNode> centroidNodes[N];
void dfsPre(int x, int par, long long dist, int root, int branchId)
{
  int preDfs = ++dfsTime;
  initialDist[preDfs] = dist;
  for (auto u : adj[x])
  {
    int y = u.first;
    if (y != par && !done[y])
      dfsPre(y, x, dist + edges[u.second].c, root, branchId);
  }
  centroidNodes[x].push_back({root, preDfs, dfsTime, branchId});
}
void initCentroid(int root)
{
  int branchId = 0;
  dfsTime = 0;
  for (auto u : adj[root])
  {
    int x = u.first;
    if (!done[x])
    {
      dfsPre(x, root, edges[u.second].c, root, branchId);
      CentroidNode node = centroidNodes[x].back();
      centroidData[root].segments.push_back({node.preDfs, node.postDfs});
      branchId++;
    }
  }
  centroidNodes[root].push_back({root, 0, dfsTime, -1});
  centroidData[root].segTree = dfsTime > 0 ? new SegmentTree(1, dfsTime, initialDist) : NULL;
  for (auto u : centroidData[root].segments)
    centroidData[root].candidates.insert(centroidData[root].segTree->get(u.first, u.second));
  ans.insert(centroidData[root].getAns());
}
void dfs(int x, int par)
{
  activeNodes.push_back(x);
  treeSize[x] = 1;
  for (auto u : adj[x])
  {
    int y = u.first;
    if (!done[y] && y != par)
    {
      dfs(y, x);
      treeSize[x] += treeSize[y];
    }
  }
}
void decompose(int x)
{
  activeNodes.clear();
  dfs(x, 0);
  int centroid = x;
  for (int y : activeNodes)
    if (treeSize[y] * 2 >= treeSize[x] && treeSize[y] < treeSize[centroid])
      centroid = y;
  initCentroid(centroid);
  done[centroid] = 1;
  for (auto u : adj[centroid])
    if (!done[u.first])
      decompose(u.first);
}
int main()
{
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  long long w, e;
  int q, x, y, d;
  long long c;
  cin >> n >> q >> w;
  for (int i = 0; i < n - 1; i++)
  {
    cin >> x >> y >> c;
    adj[x].push_back({y, i});
    adj[y].push_back({x, i});
    edges[i] = {x, y, c};
  }
  decompose(1);
  long long curAns = 0;
  while (q--)
  {
    cin >> d >> e;
    int i = (d + curAns) % (n - 1), x = edges[i].x, y = edges[i].y;
    long long newC = (e + curAns) % w, diff = newC - edges[i].c;
    edges[i].c = newC;
    for (int j = 0; j < centroidNodes[x].size() && j < centroidNodes[y].size(); j++)
    {
      auto nodeX = centroidNodes[x][j], nodeY = centroidNodes[y][j];
      if (nodeX.root != nodeY.root)
        break;
      int root = centroidNodes[x][j].root;
      if (nodeX.preDfs > nodeY.preDfs)
        swap(nodeX, nodeY);
      ans.erase(ans.find(centroidData[root].getAns()));
      auto segment = centroidData[root].segments[nodeY.branchId];
      auto &segTree = centroidData[root].segTree;
      auto &candidates = centroidData[root].candidates;
      long long u = segTree->get(segment.first, segment.second);
      candidates.erase(candidates.find(u));
      segTree->update(nodeY.preDfs, nodeY.postDfs, diff);
      candidates.insert(segTree->get(segment.first, segment.second));
      ans.insert(centroidData[root].getAns());
    }
    curAns = *ans.rbegin();
    cout << curAns << '\n';
  }
}
Compilation message (stderr)
diameter.cpp: In function 'int main()':
diameter.cpp:196:23: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<CentroidNode>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  196 |     for (int j = 0; j < centroidNodes[x].size() && j < centroidNodes[y].size(); j++)
      |                     ~~^~~~~~~~~~~~~~~~~~~~~~~~~
diameter.cpp:196:54: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<CentroidNode>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  196 |     for (int j = 0; j < centroidNodes[x].size() && j < centroidNodes[y].size(); j++)
      |                                                    ~~^~~~~~~~~~~~~~~~~~~~~~~~~| # | 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... |