#include<bits/stdc++.h>
#define lson rt<<1
#define rson rt<<1|1
using namespace std;
const int maxn=1e5+10;
const int INF=1e9;
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
return x*f;
}
int n,he[maxn],to[maxn<<1],ne[maxn<<1],tot,w[maxn<<1][2];
void addedge(int u,int v,int z,int t)
{
ne[++tot]=he[u];
he[u]=tot;
to[tot]=v;
w[tot][0]=z;
w[tot][1]=t;
}
int a[maxn],d[maxn],son[maxn],siz[maxn],fa[maxn],is[maxn];
void dfs1(int x)
{
siz[x]=1;
for (int i=he[x];i;i=ne[i])
{
if (d[to[i]]) continue;
d[to[i]]=d[x]+1;
fa[to[i]]=x;
is[w[i][1]]=to[i];
a[to[i]]=w[i][0];
dfs1(to[i]);
siz[x]+=siz[to[i]];
if (siz[to[i]]>siz[son[x]]) son[x]=to[i];
}
}
int dfn[maxn],rnk[maxn],top[maxn],tmp;
void dfs2(int x,int t)
{
dfn[x]=++tmp;
rnk[tmp]=x;
top[x]=t;
if (!son[x]) return;
dfs2(son[x],t);
for (int i=he[x];i;i=ne[i])
{
if (to[i]==son[x]||to[i]==fa[x]) continue;
dfs2(to[i],to[i]);
}
}
struct node{
int o,lz1,lz2,l,r;
}tree[maxn<<2];
void pushup(int rt)
{
tree[rt].o=max(tree[lson].o,tree[rson].o);
}
void pushdown1(int rt)
{
if (tree[rt].lz1==-1) return;
tree[lson].lz2=tree[rt].lz2=0;
int t=tree[rt].lz1;
tree[rt].lz1=-1;
tree[lson].lz1=tree[rson].lz1=t;
tree[lson].o=tree[rson].o=t;
}
void pushdown2(int rt)
{
if (!tree[rt].lz2) return;
int t=tree[rt].lz2;
tree[rt].lz2=0;
tree[lson].lz2+=t;tree[rson].lz2+=t;
tree[lson].o+=t;tree[rson].o+=t;
}
void build(int rt,int l,int r)
{
tree[rt].l=l;tree[rt].r=r;
tree[rt].lz1=-1;
if (l==r)
{
tree[rt].o=a[rnk[l]];
return;
}
int mid=(l+r)>>1;
build(lson,l,mid);
build(rson,mid+1,r);
pushup(rt);
}
void change(int rt,int pos,int val)
{
if (tree[rt].l==tree[rt].r)
{
tree[rt].o=val;
return;
}
pushdown1(rt);pushdown2(rt);
int mid=(tree[rt].l+tree[rt].r)>>1;
if (pos<=mid) change(lson,pos,val);
else change(rson,pos,val);
pushup(rt);
}
void cover(int rt,int l,int r,int val)
{
if (l<=tree[rt].l&&tree[rt].r<=r)
{
tree[rt].lz1=val;
tree[rt].o=val;
return;
}
pushdown1(rt);pushdown2(rt);
int mid=(tree[rt].l+tree[rt].r)>>1;
if (l<=mid) cover(lson,l,r,val);
if (r>mid) cover(rson,l,r,val);
pushup(rt);
}
void _cover(int x,int y,int w)
{
while (top[x]!=top[y])
{
if (d[top[x]]>d[top[y]]) swap(x,y);
cover(1,dfn[top[y]],dfn[y],w);
y=fa[top[y]];
}
if (x==y) return;
if (d[x]>d[y]) swap(x,y);
cover(1,dfn[x]+1,dfn[y],w);
}
void add(int rt,int l,int r,int val)
{
if (l<=tree[rt].l&&tree[rt].r<=r)
{
tree[rt].o+=val;
tree[rt].lz2+=val;
return;
}
pushdown1(rt);pushdown2(rt);
int mid=(tree[rt].l+tree[rt].r)>>1;
if (l<=mid) add(lson,l,r,val);
if (mid<r) add(rson,l,r,val);
pushup(rt);
}
void _add(int x,int y,int w)
{
while (top[x]!=top[y])
{
if (d[top[x]]>d[top[y]]) swap(x,y);
add(1,dfn[top[y]],dfn[y],w);
y=fa[top[y]];
}
if (x==y) return;
if (d[x]>d[y]) swap(x,y);
add(1,dfn[x]+1,dfn[y],w);
}
int query(int rt,int l,int r)
{
if (l<=tree[rt].l&&tree[rt].r<=r)
return tree[rt].o;
pushdown1(rt);pushdown2(rt);int ans=-INF;
int mid=(tree[rt].l+tree[rt].r)>>1;
if (l<=mid) ans=max(ans,query(lson,l,r));
if (mid<r) ans=max(ans,query(rson,l,r));
return ans;
}
int _query(int x,int y)
{
int ans=-INF;
while (top[x]!=top[y])
{
if (d[top[x]]>d[top[y]]) swap(x,y);
ans=max(ans,query(1,dfn[top[y]],dfn[y]));
y=fa[top[y]];
}
if (x==y) return ans;
if (d[x]>d[y]) swap(x,y);
ans=max(ans,query(1,dfn[x]+1,dfn[y]));
return ans;
}
int main()
{
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
n=read();
for (int i=1,x,y,z;i<n;i++)
{
x=read();y=read();z=read();
addedge(x,y,z,i);
addedge(y,x,z,i);
}
d[1]=1;
dfs1(1);dfs2(1,1);build(1,1,n);
string op;int k,w,u,v;
while (cin>>op)
{
if (op=="Stop") break;
else if (op=="Change")
{
k=read();w=read();
change(1,dfn[is[k]],w);
}
else if (op=="Cover")
{
u=read();v=read();w=read();
_cover(u,v,w);
}
else if (op=="Add")
{
u=read();v=read();w=read();
_add(u,v,w);
}
else if (op=="Max")
{
u=read();v=read();
printf("%d\n",_query(u,v));
}
}
fclose(stdin);
fclose(stdout);
return 0;
}