#include <bits/stdc++.h>
using namespace std;
const int MAX = 1e5 + 5;
struct segment_tree{
    vector<long long> st, lazy;
    segment_tree() : st(), lazy() {}
    void init(int n){
        st.resize(n << 2);
        lazy.resize(n << 2);
    }
    void apply(int id, long long v){
        st[id] += v;
        lazy[id] += v;
    }
    void down(int id){
        if(lazy[id] != 0){
            apply(id << 1, lazy[id]);
            apply(id << 1 | 1, lazy[id]);
            lazy[id] = 0;
        }
    }
    void update(int id, int l, int r, int u, int v, long long delta){
        if(u <= l && r <= v) apply(id, delta);
        else{
            int mid = l + r >> 1;
            down(id);
            if(u <= mid) update(id << 1, l, mid, u, v, delta);
            if(mid < v) update(id << 1 | 1, mid + 1, r, u, v, delta);
            st[id] = max(st[id << 1], st[id << 1 | 1]);
        }
    }
    long long query(int id, int l, int r, int u, int v){
        if(v < l || u > r) return 0;
        if(u <= l && r <= v) return st[id];
        int mid = l + r >> 1;
        down(id);
        return max(query(id << 1, l, mid, u, v), query(id << 1 | 1, mid + 1, r, u, v));
    }
    void build(int id, int l, int r, vector<long long>& val){
        if(l == r) st[id] = val[l];
        else{
            int mid = l + r >> 1;
            build(id << 1, l, mid, val);
            build(id << 1 | 1, mid + 1, r, val);
            st[id] = max(st[id << 1], st[id << 1 | 1]);
        }
    }
};
struct segment_2_best{
    vector<pair<long long, long long>> st;
    int n;
    segment_2_best() : st(n), n() {}
    void init(int _n){
        n = _n;
        st.resize(n * 2 + 10);
    }
    void update(int i, long long v){
        i += n;
        st[i] = {v, 0};
        for(; i > 1; i >>= 1){
            int p = i >> 1;
            st[p].first = max(st[i].first, st[i ^ 1].first);
            if(st[p].first == st[i].first) st[p].second = max(st[i].second, st[i ^ 1].first);
            else st[p].second = max(st[i].first, st[i ^ 1].second);
        }
    }
    long long sum_two_best(){
        if(st.empty()) return 0;
        assert((int)st.size() > 1);
        return st[1].first + st[1].second;
    }
};
int N, Q;
long long W;
int a[MAX], b[MAX];
long long c[MAX];
vector<int> adj_id[MAX];
int sz[MAX];
bool deleted[MAX];
segment_tree trs[MAX];
segment_2_best combinations[MAX];
long long t[MAX << 1];
void change(int i, long long v){
    i += N;
    t[i] = v;
    for(; i > 1; i >>= 1){
        t[i >> 1] = max(t[i], t[i ^ 1]);
    }
}
long long query_diameter(){
    return t[1];
}
int centroid_at[17][MAX], sz_seg[MAX];
int tin[17][MAX], tout[17][MAX], depth[MAX], id_subtree[17][MAX];
int l_sub[MAX], r_sub[MAX], represents[MAX];
int timer_subtree, timer_dfs;
vector<long long> tour(MAX), tour_subtree(MAX);
int dfs_sz(int u, int p){
    sz[u] = 1;
    for(auto id : adj_id[u]) if(p != id){
        int v = a[id] ^ b[id] ^ u;
        if(!deleted[v]) sz[u] += dfs_sz(v, id);
    }
    return sz[u];
}
int find_centroid(int u, int p, int target){
    for(auto id : adj_id[u]) if(p != id){
        int v = a[id] ^ b[id] ^ u;
        if(!deleted[v] && sz[v] * 2 > target) return find_centroid(v, id, target);
    }
    return u;
}
void initial_dfs(int u, int p, int layer, long long sum_w, int centroid){
    tour[tin[layer][u] = ++timer_dfs] = sum_w;
    id_subtree[layer][u] = timer_subtree;
    centroid_at[layer][u] = centroid;
    tour_subtree[timer_subtree] = max(tour_subtree[timer_subtree], sum_w);
//    cout << u << ' ' << p << ' ' << layer << ' ' << sum_w << ' ' << centroid << '\n';
    for(auto id : adj_id[u]) if(p != id){
        int v = a[id] ^ b[id] ^ u;
        if(deleted[v]) continue;
        if(p == -1){
            represents[++timer_subtree] = v;
        }
        initial_dfs(v, id, layer, sum_w + c[id], centroid);
    }
    tout[layer][u] = timer_dfs;
}
void decompose(int u, int dep){
    int cur = dfs_sz(u, -1);
    u = find_centroid(u, -1, cur);
    depth[u] = dep;
    timer_dfs = 0;
    l_sub[u] = timer_subtree;
    initial_dfs(u, -1, dep, 0, u);
    sz_seg[u] = timer_dfs;
    r_sub[u] = timer_subtree;
    if(r_sub[u] - l_sub[u] > 0) combinations[u].init(r_sub[u] - l_sub[u]);
    trs[u].init(sz_seg[u]);
    trs[u].build(1, 1, sz_seg[u], tour);
    for(int i = l_sub[u] + 1; i <= r_sub[u]; ++i) {
        if(l_sub[u] == r_sub[u]) assert(false);
        combinations[u].update(i - l_sub[u], tour_subtree[i]);
    }
    if(r_sub[u] - l_sub[u] > 0) {
//        cout << u << ' ' << combinations[u].sum_two_best() << '\n';
        change(u, combinations[u].sum_two_best());
    }
    deleted[u] = true;
    for(auto id : adj_id[u]){
        int v = a[id] ^ b[id] ^ u;
        if(deleted[v]) continue;
        decompose(v, dep + 1);
    }
}
void update(int id_e, long long new_w){
    long long delta = new_w - c[id_e];
    c[id_e] = new_w;
    int u = a[id_e], v = b[id_e];
    int mindep = min(depth[u], depth[v]);
    for(int i = mindep; i >= 0; --i){
        if(centroid_at[i][u] != -1 && centroid_at[i][v] != -1 && centroid_at[i][u] == centroid_at[i][v]){
            int c = centroid_at[i][u];
            if(tin[i][u] > tin[i][v]) swap(u, v);
            int id = id_subtree[i][v], k = represents[id];
            trs[c].update(1, 1, sz_seg[c], tin[i][v], tout[i][v], delta);
            int pos = id - l_sub[c];
            combinations[c].update(pos, trs[c].query(1, 1, sz_seg[c], tin[i][k], tout[i][k]));
            change(c, combinations[c].sum_two_best());
//            cout << c << " : " << combinations[c].sum_two_best() << '\n';
        }
    }
}
int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);
#ifdef LOCAL
    freopen("task.inp", "r", stdin);
    freopen("task.out", "w", stdout);
#endif // LOCAL
    cin >> N >> Q >> W;
    for(int i = 0; i + 1 < N; ++i){
        cin >> a[i] >> b[i] >> c[i];
        --a[i]; --b[i];
        adj_id[a[i]].emplace_back(i);
        adj_id[b[i]].emplace_back(i);
    }
    memset(centroid_at, -1, sizeof(centroid_at));
    decompose(0, 0);
    long long last = 0;
    while(Q--){
        int d;
        long long e;
        cin >> d >> e;
        d = ((long long)d + last) % (N - 1);
        e = (e + last) % W;
        update(d, e);
        last = query_diameter();
        cout << last << '\n';
    }
    return 0;
}
| # | 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... |