【题意】给一颗树,有3种操作,第一种是修改一条边的权值,把a-b路径上的每一条边的边权改成相反的,还有查询2个点之前的最大权值。

【解题方法】算是比较裸的树剖了,一个基本的想法是用将边权变成点权,然后其他的就是最基本的剖分了,至于取反操作,每一个改变区间的最大最小,然后交换就可以等效这个操作了。很***的是,我在单点更新没有pushdown导致wa无数发。

【AC 代码】

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 200010;
const int inf  = 1e9;
struct edge
{
    int to,next;
} E[maxn*3];
/***************************树链剖分******************************/
int head[maxn*2],tot,tim,n;
int e[maxn][3];
int siz[maxn],top[maxn],son[maxn];
int dep[maxn],Rank[maxn],tid[maxn],fa[maxn];
void Init()
{
    memset(head,-1,sizeof(head));
    memset(son,-1,sizeof(son));
    tot=tim=0;
}
void addedge(int u,int v)
{
    E[tot].to=v,E[tot].next=head[u],head[u]=tot++;
    E[tot].to=u,E[tot].next=head[v],head[v]=tot++;
}


void dfs1(int u,int father,int d)
{
    dep[u] = d;
    fa[u]  = father;
    siz[u] = 1;
    for(int i=head[u]; ~i; i=E[i].next)
    {
        int v = E[i].to;
        if(v!=father)
        {
            dfs1(v,u,d+1);
            if(son[u]==-1||siz[v]>siz[son[u]])
                son[u] = v;
        }
    }
}
void dfs2(int u,int tp)
{
    top[u]        = tp;
    tid[u]        = ++tim;
    Rank[tid[u]]  = u;
    if(son[u]==-1) return ;
    dfs2(son[u],tp);
    for(int i=head[u]; ~i; i=E[i].next)
    {
        int v=E[i].to;
        if(v!=fa[u]&&v!=son[u])
        {
            dfs2(v,v);
        }
    }
}
/****************************线段树*******************************/
struct node
{
    int l,r;
    int maxx,minn,ne;
} T[maxn<<2];
void pushup(int rt)
{
    T[rt].maxx = max(T[rt*2].maxx,T[rt*2+1].maxx);
    T[rt].minn = min(T[rt*2].minn,T[rt*2+1].minn);
}
void pushdown(int rt)
{
    if(T[rt].ne)
    {
        T[rt<<1].maxx = -T[rt<<1].maxx;
        T[rt<<1].minn = -T[rt<<1].minn;
        swap(T[rt<<1].maxx,T[rt<<1].minn);
        T[rt<<1|1].maxx = -T[rt<<1|1].maxx;
        T[rt<<1|1].minn   = -T[rt<<1|1].minn;
        swap(T[rt<<1|1].maxx,T[rt<<1|1].minn);
        T[rt<<1].ne    ^=1;
        T[rt<<1|1].ne  ^=1;
        T[rt].ne        =0;
    }
}
void Build(int l,int r,int rt)
{
    T[rt].l=l,T[rt].r=r,T[rt].maxx=0,T[rt].minn=0,T[rt].ne=0;
    if(l==r) return ;
    int mid=(l+r)/2;
    Build(l,mid,rt*2);
    Build(mid+1,r,rt*2+1);
    pushup(rt);
}
void update1(int pos,int val,int rt)//
{
    if(T[rt].l==pos&&T[rt].r==pos)
    {
        T[rt].maxx=T[rt].minn=val;
        T[rt].ne=0;
        return ;
    }
    pushdown(rt);
    int mid = (T[rt].l+T[rt].r)/2;
    if(pos<=mid) update1(pos,val,rt*2);
    else         update1(pos,val,rt*2+1);
    pushup(rt);
}
void update2(int L,int R,int rt)
{
    if(L==T[rt].l&&T[rt].r==R)
    {
        T[rt].maxx = -T[rt].maxx;
        T[rt].minn = -T[rt].minn;
        swap(T[rt].maxx,T[rt].minn);
        T[rt].ne^=1;
        return ;
    }
    pushdown(rt);
    int mid=(T[rt].l+T[rt].r)/2;
    if(R<=mid) update2(L,R,rt*2);
    else if(L>mid) update2(L,R,rt*2+1);
    else
    {
//        update2(L,R,rt*2);
//        update2(L,R,rt*2+1);
        update2(L,mid,rt*2);
        update2(mid+1,R,rt*2+1);
    }
    pushup(rt);
}
int query(int L,int R,int rt)
{
    if(T[rt].l==L&&T[rt].r==R)
    {
        return T[rt].maxx;
    }
    pushdown(rt);
    int mid=(T[rt].l+T[rt].r)/2;
    if(R<=mid) return query(L,R,rt*2);
    else if(L>mid) return query(L,R,rt*2+1);
    else
    {
//        return max(query(L,R,rt*2),query(L,R,rt*2+1));
        return max(query(L,mid,rt*2),query(mid+1,R,rt*2+1));
    }
    pushup(rt);
}
int lca(int x,int y)
{
    int ans=-100000000;
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        ans = max(ans,query(tid[top[x]],tid[x],1));
        x=fa[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    if(x!=y) ans=max(ans,query(tid[x]+1,tid[y],1));
    return ans;
}
void Negate(int x,int y)
{
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        update2(tid[top[x]],tid[x],1);
        x=fa[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    if(x!=y) update2(tid[x]+1,tid[y],1);
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        Init();
        scanf("%d",&n);
        for(int i=0; i<n-1; i++)
        {
            scanf("%d%d%d",&e[i][0],&e[i][1],&e[i][2]);
            addedge(e[i][0],e[i][1]);
        }
        dfs1(1,0,0);
        dfs2(1,1);
        Build(0,tim,1);
        for(int i=0; i<n-1; i++)
        {
            if(dep[e[i][0]]>dep[e[i][1]]) swap(e[i][0],e[i][1]);
            update1(tid[e[i][1]],e[i][2],1);
        }
        char op[10];
        int u,v;
        while(scanf("%s",op))
        {
            if(op[0]=='D') break;
            scanf("%d%d",&u,&v);
            if(op[0]=='Q')
            {
                printf("%d\n",lca(u,v));
            }
            else if(op[0]=='C')
            {
                update1(tid[e[u-1][1]],v,1);
            }
            else
                Negate(u,v);
        }
    }
    return 0;
}