题目大意:给一颗无根带边权树。支持两种操作:
1、修改某条边的边权。
2、查询当前直径。
点分树模板题,全局开一个multiset维护直径,对于每个重心开一颗线段树和一个局部multiset,用欧拉序线段树维护每一个子树中的最值,然后将其放入局部multiset。接下来取局部multiset中前两大的路径合并扔到全局multiset中,每次直接输出全局multiset的最大值即可。
#include<bits/stdc++.h>
using namespace std;
const int MAXN=200005,MAXM=400005,MAXBIT=19;
struct tnode
{
    long long max1,lazy;
    int l,r;
};
struct Segment_Tree
{
    vector<tnode>t;
    void pushdown(int root)
    {
        if(t[root].lazy!=0)
        {
            t[root].max1+=t[root].lazy;
            if(t[root].l!=t[root].r)
            {
                int ch=root<<1;
                t[ch].lazy+=t[root].lazy;
                t[ch+1].lazy+=t[root].lazy;
            }
            t[root].lazy=0;
        }
    }
    void update (int root)
    {
        int ch=root<<1;
        pushdown(ch);
        pushdown(ch+1);
        t[root].max1=max(t[ch].max1,t[ch+1].max1);
    }
    void init(const long long A[],int n)
    {
        t.resize(4*n);
        buildit(1,1,n,A);
    }
    void buildit(int root,int l,int r,const long long A[])
    {
        t[root].l=l;
        t[root].r=r;
        t[root].lazy=0;
        if(l!=r)
        {
            int mid=(l+r)>>1;
            int ch=root<<1;
            buildit(ch,l,mid,A);
            buildit(ch+1,mid+1,r,A);
            update(root);
        }
        else t[root].max1=A[l];
    }
    void change(int root,int l,int r,long long delta)
    {
        pushdown(root);
        if(l==t[root].l&&r==t[root].r)
        {
            t[root].lazy+=delta;
            pushdown(root);
            return;
        }
        int mid=(t[root].l+t[root].r)>>1;
        int ch=root<<1;
        if(r<=mid)change(ch,l,r,delta);
        else if(l>mid)change(ch+1,l,r,delta);
        else
        {
            change(ch,l,mid,delta);
            change(ch+1,mid+1,r,delta);
        }
        update(root);
    }
    long long qmax(int root,int l,int r)
    {
        pushdown(root);
        if(t[root].l==l&&t[root].r==r)
        {
            return t[root].max1;
        }
        int mid=(t[root].l+t[root].r)>>1;
        int ch=root<<1;
        if(r<=mid)return qmax(ch,l,r);
        else if(l>mid)return qmax(ch+1,l,r);
        else return max(qmax(ch,l,mid),qmax(ch+1,mid+1,r));
    }
};
Segment_Tree ST[MAXN];
int n,q,u,v,g[MAXN],tot,gravity_size[MAXN],gravity_max[MAXN],gravity,siz,g_deep[MAXN],belone[MAXN][MAXBIT],L[MAXN][MAXBIT],R[MAXN][MAXBIT],chain_top[MAXN][MAXBIT],dfn,g_fa[MAXN];
long long p_val[MAXN],temp_val[MAXN],W,last_ans,dj,ej;
bool div_vis[MAXN];
multiset<long long>tans[MAXN],ans;
struct edges
{
    int to;
    int next;
} e[MAXM<<1];
void add_edge(int from,int to)
{
    e[++tot].to=to;
    e[tot].next=g[from];
    g[from]=tot;
    return;
}
void get_gravity(int x,int fa)
{
    gravity_size[x]=1;
    gravity_max[x]=-1;
    for(int i=g[x]; i; i=e[i].next)
    {
        if(e[i].to!=fa&&!div_vis[e[i].to])
        {
            get_gravity(e[i].to,x);
            if(gravity_max[x]==-1||gravity_max[x]<gravity_size[e[i].to])
            {
                gravity_max[x]=gravity_size[e[i].to];
            }
            gravity_size[x]+=gravity_size[e[i].to];
        }
    }
    gravity_max[x]=max(gravity_max[x],siz-gravity_size[x]);
    if(gravity==-1||gravity_max[gravity]>gravity_max[x])gravity=x;
}
void get_size(int x,int fa)
{
    ++siz;
    for(int i=g[x]; i; i=e[i].next)
    {
        if(e[i].to!=fa&&!div_vis[e[i].to])
        {
            get_size(e[i].to,x);
        }
    }
}
void dfs_get_date(int now,int fa,int c_top,long long nowsum,const int &state)
{
    L[now][state]=++dfn;
    belone[now][state]=gravity;
    if(gravity==c_top)
    {
        c_top=now;
    }
    chain_top[now][state]=c_top;
    temp_val[dfn]=nowsum;
    for(int i=g[now]; i; i=e[i].next)
    {
        if(e[i].to!=fa&&!div_vis[e[i].to])
        {
            dfs_get_date(e[i].to,now,c_top,nowsum+p_val[e[i].to],state);
        }
    }
    R[now][state]=dfn;
}
long long get_template_ans(int now)
{
    if(tans[now].size()>=2)
    {
        multiset<long long>::reverse_iterator it=tans[now].rbegin();
        it++;
        return *tans[now].rbegin()+*it;
    }
    return *tans[gravity].rbegin();
}
void tree_div(int x,int pre,int deep)
{
    siz=0;
    get_size(x,-1);
    gravity=-1;
    get_gravity(x,-1);
    div_vis[gravity]=true;
    g_deep[gravity]=deep;
    dfn=0;
    dfs_get_date(gravity,-1,gravity,0,deep);
    ST[gravity].init(temp_val,siz);
    tans[gravity].insert(0);

    for(int i=g[gravity]; i; i=e[i].next)
    {
        if(!div_vis[e[i].to])
        {
            tans[gravity].insert(ST[gravity].qmax(1,L[e[i].to][deep],R[e[i].to][deep]));
        }
    }
    ans.insert(get_template_ans(gravity)+p_val[gravity]);
    int t_g=gravity;
    g_fa[t_g]=pre;
    for(int i=g[gravity]; i; i=e[i].next)
    {
        if(!div_vis[e[i].to])
        {
            tree_div(e[i].to,t_g,deep+1);
        }
    }
    return;
}
void change(int now_g,int now_p,long long preval,long long nowval)
{
    while(now_g)
    {
        int now_top=chain_top[now_p][g_deep[now_g]];
        if(now_top==now_g)
        {
            ans.erase(ans.find(get_template_ans(now_g)+preval));
            ans.insert(get_template_ans(now_g)+nowval);
        }
        else
        {
            ans.erase(ans.find(get_template_ans(now_g)+p_val[now_g]));
            long long t_temp=ST[now_g].qmax(1,L[now_top][g_deep[now_g]],R[now_top][g_deep[now_g]]);
            tans[now_g].erase(tans[now_g].find(t_temp));
            ST[now_g].change(1,L[now_p][g_deep[now_g]],R[now_p][g_deep[now_g]],nowval-preval);
            t_temp=ST[now_g].qmax(1,L[now_top][g_deep[now_g]],R[now_top][g_deep[now_g]]);
            tans[now_g].insert(t_temp);
            ans.insert(get_template_ans(now_g)+p_val[now_g]);
        }
        now_g=g_fa[now_g];
    }
    p_val[now_p]=nowval;
}
int main()
{
    scanf("%d %d %lld",&n,&q,&W);
    for(int i=1; i<n; ++i)
    {
        scanf("%d %d %lld",&u,&v,&p_val[n+i]);
        add_edge(u,n+i);
        add_edge(n+i,u);
        add_edge(v,n+i);
        add_edge(n+i,v);
    }
    tree_div(1,0,0);
    while(q--)
    {
        scanf("%lld %lld",&dj,&ej);
        dj=(dj+last_ans)%(n-1);
        ej=(ej+last_ans)%W;
        change(dj+n+1,dj+n+1,p_val[dj+n+1],ej);
        last_ans=*ans.rbegin();
        printf("%lld\n",last_ans);
    }
    return 0;
}