思路:树链剖分的一种,将边权赋值给这条边的儿子节点,(u,v)也就是v节点,u->v,然后线段树维护节点之间的关系。
注意的是,如果u,v在同一天链中的话且dep[u] < dep[v],应该query的是[Seg[u] + 1,Seg[v]]的值,如果不是的话就是这个点到链顶的最大了。
// #pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <sstream>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <vector>
#include <map>
#include <set>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <climits>
using namespace std;
// #define DEBUG
#ifdef DEBUG
#define debug(...) printf( __VA_ARGS__ )
#else
#define debug(...)
#endif
#define CLR(x) memset(x, 0,sizeof x)
#define MEM(x,y) memset(x, y,sizeof x)
#define pk push_back
template<class T> inline T Get_Max(const T&a,const T&b){return a < b?b:a;}
template<class T> inline T Get_Min(const T&a,const T&b){return a < b?a:b;}
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> ii;
const double eps = 1e-10;
const int inf = 1 << 30;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 10010;
int head[maxn], pnt[maxn<<2], cost[maxn<<2], nxt[maxn<<2], ecnt;
int fa[maxn], size[maxn], A[maxn], top[maxn], SegId[maxn], TreeId[maxn], son[maxn], dep[maxn];
int Times;
void AddEdge(int u,int v,int c){
cost[ecnt] = c;pnt[ecnt] = v;nxt[ecnt] = head[u];head[u] = ecnt++;
cost[ecnt] = c;pnt[ecnt] = u;nxt[ecnt] = head[v];head[v] = ecnt++;
}
int DFS1(int u,int pre,int deep){
dep[u] = deep;fa[u] = pre;size[u] = 1;
int tmp = 0;
for (int i = head[u];i != -1;i = nxt[i]){
int v = pnt[i];
if (v==pre) continue;
A[v] = cost[i];
int ans = DFS1(v, u,deep + 1);
size[u] += ans;
if (son[u] == -1 || ans > tmp){
tmp = ans;
son[u] = v;
}
}
return size[u];
}
void DFS2(int u,int header){
top[u] = header;
if (son[u] != -1){
SegId[u] = ++Times;
TreeId[Times] = u;
DFS2(son[u], header);
}else if (son[u] == -1){
SegId[u] = ++Times;
TreeId[Times] = u;
return ;
}
for (int i = head[u];i != -1;i = nxt[i]){
int v = pnt[i];
if (v!=fa[u]&&v!=son[u])
DFS2(v,v);
}
}
int Max[maxn << 2];
void up(int rt){
Max[rt] = max(Max[rt<<1],Max[rt<<1|1]);
}
void Build(int rt,int L,int R){
Max[rt] = -inf;
if (L == R){
Max[rt] = A[TreeId[L]];
return ;
}
int mid = (L + R)/2;
Build(rt<<1,L,mid);
Build(rt<<1|1,mid+1,R);
up(rt);
}
int QueryMax(int l,int r,int rt,int L,int R){
if (l <= L && R <= r){
return Max[rt];
}
int mid = (L+R)/2;
int ans=-inf;
if (l<=mid) ans = max(ans,QueryMax(l,r,rt<<1,L,mid));
if (r>mid) ans = max(ans,QueryMax(l,r,rt<<1|1,mid+1,R));
return ans;
}
int FindMax(int u,int v){
int f1 = top[u],f2 = top[v];
int ans = -inf;
while(f1 != f2){
if (dep[f1] < dep[f2]){
swap(f1,f2);
swap(u,v);
}
ans = max(ans,QueryMax(SegId[f1],SegId[u],1,1,Times));
u = fa[f1];
f1=top[u];
}
if (dep[u] < dep[v]){
swap(u,v);
}
if (u != v) ans = max(ans,QueryMax(SegId[v]+1,SegId[u],1,1,Times));
return ans;
}
void updata(int pos,int val,int rt,int L,int R){
if (L==R && R==pos){
Max[rt]=val;
return ;
}
int mid=(L+R)/2;
if(pos<=mid) updata(pos,val,rt<<1,L,mid);
else updata(pos,val,rt<<1|1,mid+1,R);
up(rt);
}
void Change(int pos,int val){
int u = pnt[pos], v = pnt[pos^1];
if(fa[u]==v)swap(u,v);
updata(SegId[v],val,1,1,Times);
}
int wocao[maxn<<2];
int main()
{
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int t,n;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
Times = ecnt = 0;
memset(head, -1,sizeof head);
for (int i = 1;i < n;++i){
int u,v,c;
scanf("%d%d%d",&u,&v,&c);
AddEdge(u,v,c);
wocao[i] = head[u];
}
memset(son, -1,sizeof son);
DFS1(1, -1, 1);
A[1] = -inf;
DFS2(1, 1);
Build(1,1,Times);
char op[10];
int x,y;
while(true){
scanf("%s",op);
if (op[0] == 'D') break;
scanf("%d%d",&x,&y);
if (op[0] == 'Q')
printf("%d\n",FindMax(x,y));
else Change(wocao[x],y);
}
}
return 0;
}