#include <bits/stdc++.h>
using namespace std;
#define task "DIAMETER"
#define FOR(i, a, b) for (int i = (a); i <= (b); i++)
#define FOD(i, a, b) for (int i = (a); i >= (b); i--)
#define F first
#define S second
#define ll long long 
typedef pair<int, ll> il;
typedef pair<int, int> ii;
const int N = 1e5 + 5;
struct IT {
    vector<ll> tree, lazy;
    int n;
    void init(int _n) {
        n = _n;
        tree.assign(4 * n + 3, 0);
        lazy.assign(4 * n + 3, 0);
    }
    void down(int id) {
        if (lazy[id] == 0) return;
        ll s = lazy[id];
        tree[2 * id] += s;
        lazy[2 * id] += s;
        tree[2 * id + 1] += s;
        lazy[2 * id + 1] += s;
        lazy[id] = 0;
    }
    void update(int id, int l, int r, int u, int v, ll val) {
        if (l > v || r < u) return;
        if (l >= u && r <= v) {
            tree[id] += val;
            lazy[id] += val;
            return;
        }
        down(id);
        int mid = (l + r) >> 1;
        update(2 * id, l, mid, u, v, val);
        update(2 * id + 1, mid + 1, r, u, v, val);
        tree[id] = max(tree[2 * id], tree[2 * id + 1]);
    }
    ll get(int id, int l, int r, int u, int v) {
        down(id);
        if (l > v || r < u) return 0;
        if (l >= u && r <= v) return tree[id];
        int mid = (l + r) >> 1;
        return max(get(2 * id, l, mid, u, v), get(2 * id + 1, mid + 1, r, u, v)); 
    }
    void update(int u, int v, ll val) {
        update(1, 1, n, u, v, val);
    }
    ll get(int u, int v) {
        return get(1, 1, n, u, v);
    }
} maxTree[N];
struct EDGE {
    int v, id;
    ll w;
};
int numNode, numQuery;
ll limit;
vector<EDGE> adj[N];
ll w[N];
ii edges[N];
int sz[N];
bool del[N];
int countChild(int u, int p) {
    sz[u] = 1;
    for (EDGE e : adj[u]) {
        int v = e.v;
        if (v == p || del[v]) continue;
        sz[u] += countChild(v, u);
    }
    return sz[u];
}
int centroid(int u, int p, int m) {
    for (EDGE e : adj[u]) {
        int v = e.v;
        if (v == p || del[v]) continue;
        if (sz[v] > m / 2) return centroid(v, u, m);
    }
    return u;
}
int root;
int id[N];
vector<int> in[N], out[N], com[N], sonOfRoot[N];
vector<ll> dist[N];
void addNode(int u, int p) {
    com[root].push_back(u);
    for (EDGE e : adj[u]) {
        int v = e.v;
        if (v == p || del[v]) continue;
        addNode(v, u);
    }
}
int timer = 0;
vector<int> par[N];
void prepare(int u, int p, ll dist) {
    if (u != root) in[root][id[u]] = ++timer, maxTree[root].update(timer, timer, dist);
    for (EDGE e : adj[u]) {
        int v = e.v;
        ll c = e.w;
        if (v == p || del[v]) continue;
        par[e.id].push_back(root);
        sonOfRoot[root][id[v]] = (u == root ? id[v] : sonOfRoot[root][id[u]]);
        prepare(v, u, dist + c);
    }
    if (u != root) out[root][id[u]] = timer;
}
multiset<ll, greater<ll>> branchesValues[N];
multiset<ll, greater<ll>> allValues;
int high[N];
ll diameter(multiset<ll, greater<ll>> s) {
    if (s.empty()) return 0;
    if (s.size() == 1) return *s.begin();
    else {
        auto it = s.begin();
        ll x = *it;
        it++;
        ll y = *it;
        return x + y;
    }
}
void decompose(int u) {
    root = u = centroid(u, -1, countChild(u, -1));
    del[u] = 1;
    for (EDGE e : adj[u]) {
        int v = e.v;
        if (del[v]) continue;
        addNode(v, u);
    }
    int m = com[u].size();
    if (m == 0) return;
    sort(com[u].begin(), com[u].end());
    FOR(i, 0, m - 1) id[com[u][i]] = i;
    in[u].resize(sz[u] + 1);
    out[u].resize(sz[u] + 1);
    sonOfRoot[u].resize(sz[u] + 1);
    maxTree[u].init(m);
    timer = 0;
    prepare(u, -1, 0);
    for (EDGE e : adj[u]) {
        int v = e.v;
        if (del[v]) continue;
        branchesValues[u].insert(maxTree[u].get(in[u][id[v]], out[u][id[v]]));
    }
    allValues.insert(diameter(branchesValues[u]));
    for (EDGE e : adj[u]) {
        int v = e.v;
        if (del[v]) continue;
        decompose(v);
    }
    return;
}
int ID(int root, int node) {
    return lower_bound(com[root].begin(), com[root].end(), node) - com[root].begin();
}
void update(int id, int u, int v, ll val) {
    for (int root : par[id]) {
        int ID_U = ID(root, u), ID_V = ID(root, v);
        if (root == u);
        else if (root == v) swap(ID_U, ID_V);
        else if (in[root][ID_U] > in[root][ID_V]) swap(ID_U, ID_V);
        int x = sonOfRoot[root][ID_V];
        allValues.erase(allValues.find(diameter(branchesValues[root])));
        branchesValues[root].erase(branchesValues[root].find(maxTree[root].get(in[root][x], out[root][x])));
        maxTree[root].update(in[root][ID_V], out[root][ID_V], val);
        branchesValues[root].insert(maxTree[root].get(in[root][x], out[root][x]));
        allValues.insert(diameter(branchesValues[root]));
    }
}
int main() {
    if (fopen(task".inp", "r")) {
        freopen(task".inp", "r", stdin);
        freopen(task".out", "w", stdout);
    }
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    cin >> numNode >> numQuery >> limit;
    FOR(i, 1, numNode - 1) {
        int u, v;
        cin >> u >> v >> w[i];
        edges[i] = {u, v};
        adj[u].push_back({v, i, w[i]});
        adj[v].push_back({u, i, w[i]});
    }
    decompose(1);
    ll last = 0;
    FOR(i, 1, numQuery) {
        ll edgesID;
        ll newW;
        cin >> edgesID >> newW;
        edgesID = (edgesID + last) % (numNode - 1) + 1;
        newW = (newW + last) % limit;
        
        int u, v;
        tie(u, v) = edges[edgesID];
        if (high[u] > high[v]) swap(u, v);
        update(edgesID, u, v, -w[edgesID] + newW);
        w[edgesID] = newW;
        last = *allValues.begin();
        cout << last << "\n";
    }
    return 0;
}
Compilation message (stderr)
diameter.cpp: In function 'int main()':
diameter.cpp:208:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  208 |         freopen(task".inp", "r", stdin);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
diameter.cpp:209:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  209 |         freopen(task".out", "w", stdout);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~| # | 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... |