#include <bits/stdc++.h>
using namespace std;
const long long inf = 1e18;
const int maxn = 100010;
const int maxq = 100010;
int n, q;
long long max_weight;
vector<int> adj[maxn];
struct Edge {
  int u, v;
  long long w;
  vector<pair<int, int> > intrees;
  inline int other(int nd) { return nd == u ? v : u; }
} edges[maxn];
struct Node {
  Node *ln, *rn;
  int tl, tr;
  long long maxval;
  long long lazy;
  Node() {}
  void init(int treel, int treer, vector<long long> &vec) {
    tl = treel;
    tr = treer;
    build(vec);
  }
  inline void push() {
    ln->maxval += lazy;
    ln->lazy += lazy;
    rn->maxval += lazy;
    rn->lazy += lazy;
    lazy = 0;
  }
  inline void merge() { maxval = max(ln->maxval, rn->maxval); }
  void build(vector<long long> &vec) {
    lazy = 0;
    if (tl == tr) {
      maxval = vec[tl];
    } else {
      int tm = (tl + tr) / 2;
      ln = new Node();
      rn = new Node();
      ln->init(tl, tm, vec);
      rn->init(tm + 1, tr, vec);
      merge();
    }
  }
  void update(int l, int r, long long val) {
    if (l > r) {
      return;
    }
    if (l <= tl && tr <= r) {
      maxval += val;
      lazy += val;
      return;
    }
    push();
    ln->update(l, min(r, ln->tr), val);
    rn->update(max(l, rn->tl), r, val);
    merge();
  }
  long long query(int l, int r) {
    if (l > r) {
      return 0;
    }
    if (l <= tl && tr <= r) {
      return maxval;
    }
    push();
    return max(ln->query(l, min(r, ln->tr)), rn->query(max(l, rn->tl), r));
  }
  void set_single(int i, long long val) {
    if (tl == tr) {
      maxval = val;
      lazy = 0;
      return;
    }
    if (i <= ln->tr) {
      ln->set_single(i, val);
    } else {
      rn->set_single(i, val);
    }
    merge();
  }
} trees[maxn];
Node best_path;
bool removed[maxn];
int sbsz_cdecompose[maxn];
int num_calls;
unordered_map<int, int> label[maxn];
vector<int> sbsz[maxn];
vector<int> panc[maxn];
multiset<long long> panc_data[maxn];
int dfs_centroid(int centroid, vector<long long> &distances, int u, int p,
                 long long dist, int p2) {
  distances.push_back(dist);
  int label_u = num_calls++;
  label[centroid][u] = label_u;
  sbsz[centroid].push_back(1);
  if (p2 == -1 && u != centroid) {
    p2 = label_u;
  }
  panc[centroid].push_back(p2);
  for (int i : adj[u]) {
    int v = edges[i].other(u);
    if (v != p && !removed[v]) {
      edges[i].intrees.emplace_back(centroid, v);
      int label_v =
          dfs_centroid(centroid, distances, v, u, dist + edges[i].w, p2);
      sbsz[centroid][label_u] += sbsz[centroid][label_v];
    }
  }
  return label_u;
}
inline void get_centroid_best_path(int centroid) {
  long long res = 0;
  int i = 0;
  for (auto it = panc_data[centroid].rbegin();
       i < 2 && it != panc_data[centroid].rend(); ++i, ++it) {
    res += *it;
  }
  best_path.set_single(centroid, res);
}
inline void solve_centroid(int centroid) {
  vector<long long> distances;
  num_calls = 0;
  dfs_centroid(centroid, distances, centroid, -1, 0, -1);
  trees[centroid].init(0, num_calls - 1, distances);
  for (int i : adj[centroid]) {
    int v = edges[i].other(centroid);
    if (!removed[v]) {
      int label_v = label[centroid][v];
      panc_data[centroid].insert(trees[centroid].query(
          label_v, label_v + sbsz[centroid][label_v] - 1));
    }
  }
  get_centroid_best_path(centroid);
}
void dfs_sbsz_cdecompose(int u, int p) {
  sbsz_cdecompose[u] = 1;
  for (int i : adj[u]) {
    int v = edges[i].other(u);
    if (v != p && !removed[v]) {
      dfs_sbsz_cdecompose(v, u);
      sbsz_cdecompose[u] += sbsz_cdecompose[v];
    }
  }
}
int find_centroid(int u, int p, int sz) {
  for (int i : adj[u]) {
    int v = edges[i].other(u);
    if (v != p && !removed[v] && sbsz_cdecompose[v] > sz / 2) {
      return find_centroid(v, u, sz);
    }
  }
  return u;
}
void cdecompose(int root, int parent) {
  dfs_sbsz_cdecompose(root, parent);
  int centroid = find_centroid(root, parent, sbsz_cdecompose[root]);
  solve_centroid(centroid);
  removed[centroid] = true;
  for (int i : adj[centroid]) {
    int v = edges[i].other(centroid);
    if (!removed[v]) {
      cdecompose(v, centroid);
    }
  }
  removed[centroid] = false;
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cin >> n >> q >> max_weight;
  for (int i = 0; i < n - 1; ++i) {
    cin >> edges[i].u >> edges[i].v >> edges[i].w;
    adj[edges[i].u].push_back(i);
    adj[edges[i].v].push_back(i);
  }
  {
    vector<long long> aux(n + 1, 0);
    best_path.init(1, n, aux);
  }
  memset(removed, false, sizeof(removed));
  cdecompose(1, -1);
  long long last = 0;
  while (q--) {
    long long eid, new_w;
    cin >> eid >> new_w;
    eid = (eid + last) % (n - 1);
    new_w = (new_w + last) % max_weight;
    long long change = new_w - edges[eid].w;
    for (pair<int, int> &t : edges[eid].intrees) {
      int centroid = t.first;
      int v = t.second;
      int label_v = label[centroid][v];
      int label_p = panc[centroid][label_v];
      long long prev_data =
          trees[centroid].query(label_p, label_p + sbsz[centroid][label_p] - 1);
      trees[centroid].update(label_v, label_v + sbsz[centroid][label_v] - 1,
                             change);
      panc_data[centroid].erase(panc_data[centroid].find(prev_data));
      panc_data[centroid].insert(trees[centroid].query(
          label_p, label_p + sbsz[centroid][label_p] - 1));
      get_centroid_best_path(centroid);
    }
    edges[eid].w = new_w;
    last = best_path.maxval;
    cout << last << '\n';
  }
}
