題目連接:http://www.spoj.com/problems/QTREE/
題目大意:給你一棵帶邊權的樹,有兩個操作,1,改變某條邊的邊權;2,查詢兩個點之間的最大邊權
解題思路:解題思路是樹鏈剖分。其實就是沒有辦法直接暴力了,然後找一個方法,將邊分分類,最好能降到一維,然後再維護一下,搞一搞,就行了
這個題的特點是樹的結構不會變!!!而且有一個神結論(我比較弱,就當做是神結論吧),將一棵樹分完輕重邊之後,任意一個點到根節點的輕邊和重鏈的個數都不會超過logn。這是有個非常優美的性質,也就是說現在,對於詢問,只要分別處理兩個節點到最近公共祖先路徑上的最大值,就得到最終的結果了
//#pragma comment(linker,"/STACK:102400000,102400000")
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<string>
#define ll long long
#define db double
#define PB push_back
using namespace std;
const int N = 10005;
const int M = 2*N;
int d[N][3],num;
int head[N],cost[M],to[M],next[M],nedge;
void init()
{
memset(head,-1,sizeof(head));
nedge=0;
num=0;
}
void add(int a,int b,int c)
{
cost[nedge]=c,to[nedge]=b,next[nedge]=head[a],head[a]=nedge++;
}
int son[N],tol[N],dep[N],fa[N];
void get_son_dep(int k,int dp)
{
tol[k]=1,son[k]=0,dep[k]=dp;
for(int i=head[k];i>=0;i=next[i])
{
if(to[i]!=fa[k])
{
fa[to[i]]=k;
get_son_dep(to[i],dp+1);
tol[k]+=tol[to[i]];
if(tol[to[i]]>tol[son[k]]) son[k]=to[i];
}
}
}
int w[N],top[N];
void build(int k,int rt)
{
w[k]=++num,top[k]=rt;
if(son[k]!=0) build(son[k],rt);
for(int i=head[k];i>=0;i=next[i])
{
if(to[i]!=fa[k]&&to[i]!=son[k])
{
build(to[i],to[i]);
}
}
}
struct node
{
int l,r;
int max_val;
} tr[4*N];
void build_tr(int k,int l,int r)
{
tr[k].l=l,tr[k].r=r;
tr[k].max_val=0;
if(l<r)
{
int mid=(l+r)>>1;
build_tr(k<<1,l,mid);
build_tr((k<<1)|1,mid+1,r);
}
}
void update(int k,int lr,int val)
{
if(tr[k].l==tr[k].r)
{
tr[k].max_val=val;
return;
}
int mid=(tr[k].l+tr[k].r)>>1;
if(lr<=mid) update(k<<1,lr,val);
else update((k<<1)|1,lr,val);
tr[k].max_val=max(tr[k<<1].max_val,tr[(k<<1)|1].max_val);
}
int query(int k,int l,int r)
{
if(tr[k].l==l&&tr[k].r==r)
{
return tr[k].max_val;
}
int mid=(tr[k].l+tr[k].r)>>1;
if(r<=mid) return query(k<<1,l,r);
else if(l>=mid+1) return query((k<<1)|1,l,r);
else return max(query(k<<1,l,mid),query((k<<1)|1,mid+1,r));
}
int find_ans(int a,int b)
{
int res=0;
int tpa=top[a],tpb=top[b];
while(tpa!=tpb)
{
if(dep[tpa]<dep[tpb]) {swap(tpa,tpb),swap(a,b);}
res=max(res,query(1,w[tpa],w[a]));
a=fa[tpa],tpa=top[a];
}
if(dep[a]<dep[b]) swap(a,b);
if(a!=b) res=max(res,query(1,w[son[b]],w[a]));
return res;
}
int get_int()
{
char c;
while((c=getchar())<'0'||c>'9');
int res=c-'0';
while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
return res;
}
char str[50];
int main()
{
#ifdef PKWV
freopen("in.in","r",stdin);
#endif // PKWV
int T;
scanf("%d",&T);
while(T--)
{
int n;
n=get_int();
// scanf("%d",&n);
int rt=n/2+1;
init();
for(int i=1;i<n;i++)
{
int a,b,c;
a=get_int();b=get_int(),c=get_int();
// scanf("%d%d%d",&a,&b,&c);
d[i][0]=a,d[i][1]=b,d[i][2]=c;
add(a,b,c),add(b,a,c);
}
fa[rt]=0;
get_son_dep(rt,0);
build(rt,rt);
build_tr(1,1,num);
for(int i=1;i<n;i++)
{
if(dep[d[i][0]]>dep[d[i][1]]) swap(d[i][0],d[i][1]);
update(1,w[d[i][1]],d[i][2]);
}
while(scanf("%s",str)&&str[0]!='D')
{
int a,b;
a=get_int();b=get_int();
// scanf("%d%d",&a,&b);
if(str[0]=='C') update(1,w[d[a][1]],b);
else printf("%d\n",find_ans(a,b));
}
}
return 0;
}