#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
using namespace std;
char buf[100000], *p1 = buf, *p2 = buf;
inline long long gi() {
  long long x = 0, f = 1;
  char ch =
      (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2)
           ? EOF
           : *p1++);
  while (ch < '0' || ch > '9') {
    if (ch == '-') f = -1;
    ch = (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2)
              ? EOF
              : *p1++);
  }
  while (ch >= '0' && ch <= '9') {
    x = (x << 3) + (x << 1) + (ch ^ 48),
    ch = (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2)
              ? EOF
              : *p1++);
  }
  return (f == 1) ? x : -x;
}
const int maxn = 1e5 + 5;
const long long inf = 1e18;
int n, q, a, b;
long long W;
int u[maxn], v[maxn];
vector<pair<int, long long> > e[maxn];
long long dep[maxn], w[maxn];
struct Matrix {
  long long a[3][3];
  inline void clear() { memset(a, 0xcf, sizeof(a)); }
  inline Matrix operator*(const Matrix &b) const {
    Matrix c;
    c.clear();
    for (int k = 0; k <= 2; ++k)
      for (int i = 0; i <= 2; ++i)
        for (int j = 0; j <= 2; ++j)
          c.a[i][j] = max(c.a[i][j], a[i][k] + b.a[k][j]);
    return c;
  }
};
int dfn[maxn], tot, son[maxn];
long long f[maxn][2];
int fa[maxn], tp[maxn], bot[maxn], siz[maxn], rk[maxn];
inline void dfs(int u) {
  dep[u] = dep[fa[u]] + 1;
  siz[u] = 1;
  f[u][0] = f[u][1] = 0;
  for (auto x : e[u]) {
    int v = x.first;
    long long w = x.second;
    if (v == fa[u]) continue;
    fa[v] = u, dfs(v), siz[u] += siz[v];
    if (siz[v] > siz[son[u]]) son[u] = v;
    f[u][1] = max(f[u][1], max(f[v][1], f[u][0] + f[v][0] + w));
    f[u][0] = max(f[u][0], f[v][0] + w);
  }
  f[u][1] = max(f[u][1], f[u][0]);
}
Matrix now[maxn];
multiset<long long> s[maxn], s2[maxn];
long long val[maxn];
inline void work(int u) {
  memset(now[u].a, 0, sizeof(now[u].a));
  if (!son[u]) return now[u].a[0][0] = val[u], void();
  now[u].a[0][0] = val[u];
  now[u].a[0][1] = now[u].a[2][0] = now[u].a[2][1] = -inf;
  if (!s[u].empty()) now[u].a[0][2] = *(--s[u].end());
  now[u].a[1][0] = now[u].a[0][2], now[u].a[0][2] += val[u];
  if (!s2[u].empty()) now[u].a[1][2] = *(--s2[u].end());
  now[u].a[1][2] = max(now[u].a[1][2], now[u].a[1][0]);
  if (s[u].size() >= 2)
    now[u].a[1][2] =
        max(now[u].a[1][2], *(--s[u].end()) + (*(--(--s[u].end()))));
}
inline void dfs2(int u, int topf) {
  s[u].clear();
  dfn[u] = ++tot, rk[tot] = u;
  tp[u] = topf;
  if (son[u])
    dfs2(son[u], topf), bot[u] = bot[son[u]];
  else
    bot[u] = u;
  for (auto x : e[u]) {
    int v = x.first;
    long long w = val[v];
    if (v == fa[u] || v == son[u]) continue;
    dfs2(v, v);
    s[u].insert(f[v][0] + w);
    s2[u].insert(f[v][1]);
  }
  work(u);
}
struct segmentree {
  static const int maxn = 4e5 + 5;
  Matrix sum[maxn];
  inline void pushup(int u) { sum[u] = sum[u << 1] * sum[u << 1 | 1]; }
  inline void build(int u, int l, int r) {
    if (l == r) return sum[u] = now[rk[l]], void();
    int mid = (l + r) >> 1;
    build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
    pushup(u);
  }
  inline void update(int u, int l, int r, int x) {
    if (l == r) return sum[u] = now[rk[l]], void();
    int mid = (l + r) >> 1;
    if (x <= mid)
      update(u << 1, l, mid, x);
    else
      update(u << 1 | 1, mid + 1, r, x);
    pushup(u);
  }
  inline Matrix query(int u, int l, int r, int x, int y) {
    if (x <= l && y >= r) return sum[u];
    int mid = (l + r) >> 1;
    if (y <= mid) return query(u << 1, l, mid, x, y);
    if (x > mid) return query(u << 1 | 1, mid + 1, r, x, y);
    return query(u << 1, l, mid, x, y) * query(u << 1 | 1, mid + 1, r, x, y);
  }
} tree;
inline void update(int v, long long w) {
  now[v].a[0][0] += w, now[v].a[0][2] += w;
  while (v) {
    Matrix temp = tree.query(1, 1, n, dfn[tp[v]], dfn[bot[v]]);
    tree.update(1, 1, n, dfn[v]);
    if (tp[v] != 1) {
      int u = v;
      Matrix temp2 = tree.query(1, 1, n, dfn[tp[u]], dfn[bot[u]]);
      s[fa[tp[u]]].erase(s[fa[tp[u]]].find(temp.a[0][0]));
      s[fa[tp[u]]].insert(temp2.a[0][0]);
      s2[fa[tp[u]]].erase(s2[fa[tp[u]]].find(temp.a[1][0]));
      s2[fa[tp[u]]].insert(temp2.a[1][0]);
      work(fa[tp[u]]);
    }
    v = fa[tp[v]];
  }
}
inline void init() {}
inline void input() {
  n = gi(), q = gi(), W = gi();
  for (int i = 1; i <= n - 1; ++i) {
    u[i] = gi(), v[i] = gi(), w[i] = gi();
    e[u[i]].push_back({v[i], w[i]});
    e[v[i]].push_back({u[i], w[i]});
  }
}
inline void solve() {
  dfs(1);
  for (int i = 1; i <= n - 1; ++i)
    if (dep[u[i]] > dep[v[i]]) swap(u[i], v[i]);
  for (int i = 1; i <= n - 1; ++i) val[v[i]] = w[i];
  dfs2(1, 1);
  tree.build(1, 1, n);
  long long ans = 0;
  for (int i = 1; i <= q; ++i) {
    int d = gi();
    long long value = gi();
    d = (d + ans) % (n - 1) + 1, value = (value + ans) % W;
    update(v[d], value - val[v[d]]);
    val[v[d]] = value;
    ans = tree.query(1, 1, n, dfn[1], dfn[bot[1]]).a[1][0];
    printf("%lld\n", ans);
  }
}
int main() {
  init();
  input();
  solve();
  return 0;
}
