题目链接:点击打开链接
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=101010+5;
const int maxm=maxn+maxn;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
struct EDGENODE{
int to;
int w;
int next;
}edges[maxm];
int head[maxn],edge;
inline void init(){
edge=0;
memset(head,-1,sizeof(head));
}
inline void addedge(int u,int v,int w){
edges[edge].w=w,edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++;
edges[edge].w=w,edges[edge].to=u,edges[edge].next=head[v],head[v]=edge++;
}
int que[maxn]; // 队列
bool vis[maxn]; // 访问标记
int son[maxn]; // 重儿子
int idx[maxn]; // 结点v在其路径中的编号
int dep[maxn]; // 结点v的深度
int siz[maxn]; // 以结点v为根的子树的结点个数
int belong[maxn]; // 结点v所属的路径编号
int fa[maxn]; // 结点v的父亲结点
int top[maxn]; // 编号为p的路径的顶端结点
int len[maxn]; // 路径p的长度
int sump[maxn]; // 路径p的编号
int seg[maxn]; // 结点v的父边在线段树中的位置
int wei[maxn]; // 结点v的父边的权值
int l,r,ans,cnt;
int n;
char cmd[22];
int num[maxn];
void split(){
memset(dep,-1,sizeof(dep));
l=0;
dep[ que[r=1]=1 ]=0; // 将根结点插入队列,并设深度为0
fa[1]=-1; // 默认 1 为根结点
wei[1]=0;
while (l<r){ // 第一遍搜索求出 fa,dep,wei
int u=que[++l];
vis[u]=false; // 顺便初始化vis
for (int i=head[u];i!=-1;i=edges[i].next){
int v=edges[i].to;
int w=edges[i].w;
if (dep[v]==-1){ // 未访问过的结点
dep[ que[++r]=v ]=dep[u]+1; // 将v插入队列并设深度为dep[u]+1
fa[v]=u; // v的父结点为u
wei[v]=w; // v的父边权值
}
}
}
cnt=0; // 重链编号
for (int i=n;i>0;i--){
int u=que[i],p=-1;
siz[u]=1;
son[u]=p;
for (int k=head[u];k!=-1;k=edges[k].next){
int v=edges[k].to;
if (vis[v]){ // 若v是u的子结点
siz[u]+=siz[v]; // 计数
if (p==-1||siz[v]>siz[p]){
son[u]=v;
p=v; // u的重儿子是v
}
}
}
if (p==-1){ // u是叶子结点
idx[u]=len[++cnt]=1; // 一个新的路径编号为cnt,u是路径中的第一个结点
belong[ top[cnt]=u ]=cnt; // u是顶端结点,且u属于路径cnt
}
else{ // u不是叶子结点
idx[u]=++len[ belong[u]=belong[p] ]; // u属于重儿子所在的链,链长+1,u是路径中第len个结点
top[ belong[u] ]=u; // u是顶端结点
}
vis[u]=true; // 访问标记
}
}
struct tree
{
int maxx[maxn<<2];
bool lazy[maxn<<2];
void pushup(int rt)
{
maxx[rt]=max(maxx[rt<<1],maxx[rt<<1|1]);
}
void build(int l,int r,int rt)
{
if(l==r)
{
maxx[rt]=num[l];
return ;
}
int m=(l+r)>>1;
build(lson);
build(rson);
pushup(rt);
}
void update(int add,int flag,int l,int r,int rt)
{
if(l==r)
{
maxx[rt]=add;
return ;
}
int m=(l+r)>>1;
if(flag<=m)
update(add,flag,lson);
else update(add,flag,rson);
pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
return maxx[rt];
}
int m=(l+r)>>1,ans=0;
if(L<=m)
ans=max(ans,query(L,R,lson));
if(R>m)
ans=max(ans,query(L,R,rson));
return ans;
}
}xixixi;
int find(int va,int vb){
int f1=top[belong[va]],f2=top[belong[vb]],tmp=0;
while (f1!=f2){
if (dep[f1]<dep[f2]){
swap(f1,f2);
swap(va,vb);
}
tmp=max(tmp,xixixi.query(seg[f1],seg[va],1,n,1));
va=fa[f1];
f1=top[belong[va]];
}
if (va==vb) return tmp;
if (dep[va]>dep[vb]) swap(va,vb);
return max(tmp,xixixi.query(seg[son[va]],seg[vb],1,n,1));
}
int d[maxn][3];
int main()
{
int T;
scanf("%d",&T);
while (T--){
init();
scanf("%d",&n);
for (int i=1;i<n;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
d[i][0]=a;
d[i][1]=b;
d[i][2]=c;
addedge(a,b,c);
}
split();
sump[0]=0;
for (int i=1;i<=cnt;i++) sump[i]=sump[i-1]+len[i];
for (int i=1;i<=n;i++){
seg[i]=sump[ belong[i] ]-idx[i]+1;
num[ seg[i] ]=wei[i];
}
xixixi.build(1,n,1);
while (scanf("%s",cmd)){
if (cmd[0]=='D') break;
int x,y;
scanf("%d%d",&x,&y);
if (cmd[0]=='Q'){
printf("%d\n",find(x,y));
}
if (cmd[0]=='C'){
if (fa[d[x][1]]==d[x][0]) xixixi.update(y,seg[d[x][1]],1,n,1);
else xixixi.update(y,seg[d[x][0]],1,n,1);
}
}
}
return 0;
}