rt
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL maxn=2e5+7;
LL N,M;
struct SegmentTree{
struct Node{
Node* ls=nullptr,* rs=nullptr;
LL Sum,Min=0x3f,Max=-0x3f,oppov;
}root;
#define ls(p) p.ls
#define rs(p) p.rs
void pushup(Node& p){
p.Sum=p.ls->Sum+p.rs->Sum;
p.Max=max(p.ls->Max,p.rs->Max);
p.Min=min(p.ls->Min,p.rs->Min);
}
void pushdown(Node& p){
if(!ls(p))ls(p)=new Node();
if(!rs(p))rs(p)=new Node();
if(p.oppov){
p.ls->oppov^=p.oppov;p.rs->oppov^=p.oppov;
p.ls->Sum*=-1;p.rs->Sum*=-1;
p.ls->Min*=-1;p.rs->Min*=-1;
p.ls->Max*=-1;p.rs->Max*=-1;
swap(p.ls->Min,p.ls->Max);
swap(p.rs->Min,p.rs->Max);
p.oppov=0;
}
}
void ModifyPoint(Node& p,LL L,LL R,LL inx,LL xx){
if(L>=R){p.Sum=p.Max=p.Min=xx;return;}
pushdown(p);
LL mid=(L+R)>>1;
if(inx<=mid)ModifyPoint(*ls(p),L,mid,inx,xx);
else ModifyPoint(*rs(p),mid+1,R,inx,xx);
pushup(p);
}
void ModifyPoint(LL inx,LL xx){ModifyPoint(root,1,N,inx,xx);}
void ModifyRange(Node& p,LL L,LL R,LL ql,LL qr){
if(ql<=L&&R<=qr){
p.Sum*=-1;p.Min*=-1;p.Max*=-1;
swap(p.Min,p.Max);
p.oppov^=1;return;
}
pushdown(p);LL mid=(L+R)>>1;
if(ql<=mid)ModifyRange(*ls(p),L,mid,ql,qr);
if(mid+1<=qr)ModifyRange(*rs(p),mid+1,R,ql,qr);
pushup(p);
}
void ModifyRange(LL ql,LL qr){ModifyRange(root,1,N,ql,qr);}
LL QueryRangeSum(Node& p,LL L,LL R,LL ql,LL qr){
if(ql<=L&&R<=qr)return p.Sum;
pushdown(p);
LL mid=(L+R)>>1,ret=0;
if(ql<=mid)ret+=QueryRangeSum(*ls(p),L,mid,ql,qr);
if(mid+1<=qr)ret+=QueryRangeSum(*rs(p),mid+1,R,ql,qr);
return ret;
}
LL QueryRangeSum(LL ql,LL qr){return QueryRangeSum(root,1,N,ql,qr);}
LL QueryRangeMax(Node& p,LL L,LL R,LL ql,LL qr){
if(ql<=L&&R<=qr)return p.Max;
pushdown(p);
LL mid=(L+R)>>1,ret=-0x3f;
if(ql<=mid)ret=max(ret,QueryRangeMax(*ls(p),L,mid,ql,qr));
if(mid+1<=qr)ret=max(ret,QueryRangeMax(*rs(p),mid+1,R,ql,qr));
return ret;
}
LL QueryRangeMax(LL ql,LL qr){return QueryRangeMax(root,1,N,ql,qr);}
LL QueryRangeMin(Node& p,LL L,LL R,LL ql,LL qr){
if(ql<=L&&R<=qr)return p.Min;
pushdown(p);
LL mid=(L+R)>>1,ret=0x3f;
if(ql<=mid)ret=min(ret,QueryRangeMin(*ls(p),L,mid,ql,qr));
if(mid+1<=qr)ret=min(ret,QueryRangeMin(*rs(p),mid+1,R,ql,qr));
return ret;
}
LL QueryRangeMin(LL ql,LL qr){return QueryRangeMin(root,1,N,ql,qr);}
};
struct SLPF{
LL head[maxn<<1],nxt[maxn<<1],to[maxn<<1],cnt_edge;
LL dep[maxn],f[maxn],id[maxn],Hson[maxn],Hd[maxn],size[maxn],dfn;
LL w[maxn],val[maxn],id_edge[maxn],down[maxn];
SegmentTree SEG;
void AddEdge(LL u,LL v,LL _w,LL _id){
nxt[++cnt_edge]=head[u];to[cnt_edge]=v;
head[u]=cnt_edge;w[cnt_edge]=_w;id_edge[cnt_edge]=_id;
nxt[++cnt_edge]=head[v];to[cnt_edge]=u;
head[v]=cnt_edge;w[cnt_edge]=_w;id_edge[cnt_edge]=_id;
}
void dfs1(LL u,LL fa,LL _w,LL _id){
dep[u]=dep[fa]+1;f[u]=fa;size[u]=1;
val[u]=_w;down[_id]=u;
for(int i=head[u];i;i=nxt[i]){
if(to[i]==fa)continue;
dfs1(to[i],u,w[i],id_edge[i]);
size[u]+=size[to[i]];
if(size[to[i]]>size[Hson[u]])Hson[u]=to[i];
}
}
void dfs2(LL u,LL top){
id[u]=++dfn;Hd[u]=top;
if(!Hson[u])return;dfs2(Hson[u],top);
for(int i=head[u];i;i=nxt[i]){
if(to[i]==f[u]||to[i]==Hson[u])continue;
dfs2(to[i],to[i]);
}
}
void init(){
scanf("%lld",&N);
for(int i=1;i<N;i++){
LL a,b,c;scanf("%lld%lld%lld",&a,&b,&c);
AddEdge(a+1,b+1,c,i);
}
dfs1(1,0,0,0);dfs2(1,1);
for(int i=1;i<=N;i++)SEG.ModifyPoint(id[i],val[id[i]]);
}
void ModifyEdgeOnTree(LL e,LL xx){SEG.ModifyPoint(id[down[e]],xx);}
void ModifyRangeOnTree(LL u,LL v){
while(Hd[u]!=Hd[v]){
if(dep[Hd[u]]<dep[Hd[v]])swap(u,v);
SEG.ModifyRange(id[Hd[u]],id[u]);
u=f[Hd[u]];
}
if(dep[u]<dep[v])swap(u,v);
if(id[u]!=id[v])SEG.ModifyRange(id[Hson[v]],id[u]);
}
LL QuerySumOnTree(LL u,LL v){
LL ret=0;
while(Hd[u]!=Hd[v]){
if(dep[Hd[u]]<dep[Hd[v]])swap(u,v);
ret+=SEG.QueryRangeSum(id[Hd[u]],id[u]);
u=f[Hd[u]];
}
if(dep[u]<dep[v])swap(u,v);
if(id[u]!=id[v])ret+=SEG.QueryRangeSum(id[Hson[v]],id[u]);return ret;
}
LL QueryMaxOnTree(LL u,LL v){
LL ret=-0x3f;
while(Hd[u]!=Hd[v]){
if(dep[Hd[u]]<dep[Hd[v]])swap(u,v);
ret=max(ret,SEG.QueryRangeMax(id[Hd[u]],id[u]));
u=f[Hd[u]];
}
if(dep[u]<dep[v])swap(u,v);
if(id[u]!=id[v])ret=max(ret,SEG.QueryRangeMax(id[Hson[v]],id[u]));return ret;
}
LL QueryMinOnTree(LL u,LL v){
LL ret=0x3f;
while(Hd[u]!=Hd[v]){
if(dep[Hd[u]]<dep[Hd[v]])swap(u,v);
ret=min(ret,SEG.QueryRangeMin(id[Hd[u]],id[u]));
u=f[Hd[u]];
}
if(dep[u]<dep[v])swap(u,v);
if(id[u]!=id[v])ret=min(ret,SEG.QueryRangeMin(id[Hson[v]],id[u]));return ret;
}
void Query(){
scanf("%lld",&M);
while(M--){
char op[6];LL a,b;
scanf("%s",op);scanf("%lld%lld",&a,&b);
if(op[0]=='C'){ModifyEdgeOnTree(a,b);}
else if(op[0]=='N'){ModifyRangeOnTree(a+1,b+1);}
else if(op[0]=='S'){printf("%lld\n",QuerySumOnTree(a+1,b+1));}
else if(op[0]=='M'&&op[1]=='A'){printf("%lld\n",QueryMaxOnTree(a+1,b+1));}
else if(op[0]=='M'&&op[1]=='I'){printf("%lld\n",QueryMinOnTree(a+1,b+1));}
}
}
}Tree;
int main(){
Tree.init();Tree.Query();
return 0;
}