/*
Work by: Suzt_ilymics
Knowledge: ??
Time: O(??)
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstring>
using namespace std;
const int MAXN = 1e5+5;
int n;
string s;
int a[MAXN];
int dfn[MAXN], pre[MAXN], son[MAXN], fath[MAXN], siz[MAXN], dep[MAXN], top[MAXN];
int read(){
int s = 0, w = 1;
char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') w = -1;ch = getchar();}
while(ch <= '9' && ch >= '0'){s = (s << 1) + (s << 3) + ch - '0';ch = getchar();}
return s * w;
}
namespace Seg{
#define lson i << 1
#define rson i << 1 | 1
struct Tree{
int lazy, len, cover, max;
}tree[MAXN << 2];
void push_up(int i){
tree[i].max = max(tree[lson].max, tree[rson].max);
return ;
}
void pushdown(int i){
if(tree[i].cover >= 0){
tree[lson].max = tree[i].cover;
tree[rson].max = tree[i].cover;
tree[lson].cover = tree[i].cover;
tree[rson].cover = tree[i].cover;
tree[i].cover = -1;
tree[lson].lazy = tree[rson].lazy = 0;
}
if(tree[i].lazy){
tree[lson].lazy += tree[i].lazy;
tree[rson].lazy += tree[i].lazy;
tree[lson].max += tree[lson].lazy;
tree[rson].max += tree[rson].lazy;
tree[i].lazy = 0;
}
return ;
}
void build(int i, int l, int r){
tree[i].lazy = 0, tree[i].cover = -1, tree[i].len = r - l + 1;
if(l == r){
tree[i].max = a[pre[l]];
return ;
}
int mid = (l + r) >> 1;
build(lson, l, mid), build(rson, mid + 1, r);
push_up(i);
return ;
}
void add(int i, int l, int r, int L, int R, int k){
if(L <= l && r <= R){
tree[i].max += k;
tree[i].lazy += k;
return ;
}
if(l > R && r < L) return ;
pushdown(i);
int mid = (l + r) >> 1;
if(mid >= L) add(lson, l, mid, L, R, k);
if(mid < R) add(rson, mid + 1, r, L, R, k);
push_up(i);
return ;
}
void cover(int i, int l, int r, int L, int R, int k){
if(L <= l && r <= R){
tree[i].max = k;
tree[i].cover = k;
tree[i].lazy = 0;
return ;
}
if(l > R && r < L) return ;
pushdown(i);
int mid = (l + r) >> 1;
if(mid >= L) cover(lson, l, mid, L, R, k);
if(mid < R) cover(rson, mid + 1, r, L, R, k);
push_up(i);
return ;
}
int get_max(int i, int l, int r, int L, int R){
int maxn = -1e9 + 7;
if(L <= l && r <= R){
return tree[i].max;
}
if(l > R && r < L) return 0;
pushdown(i);
int mid = (l + r) >> 1;
if(mid >= L) maxn = max(maxn, get_max(lson, l, mid, L, R));
if(mid < R) maxn = max(maxn, get_max(rson, mid + 1, r, L, R));
push_up(i);
return maxn;
}
}
namespace Cut{
int num_edge = 0, cnt = 0, head[MAXN << 1] = {0};
struct edge{
int to, w, nxt;
}e[MAXN << 1];
void add(int from, int to, int w){
e[++num_edge].nxt = head[from];
e[num_edge].to = to;
e[num_edge].w = w;
head[from] = num_edge;
}
void dfs(int x, int fa){
siz[x] = 1, fath[x] = fa, dep[x] = dep[fa] + 1;
for(int i = head[x]; i; i = e[i].nxt){
int v = e[i].to;
if(v == fa) continue;
a[v] = e[i].w;//将边权转移到点上
dfs(v, x);
siz[x] += siz[v];
if(siz[son[x]] < siz[v]) son[x] = v;
}
}
void dfs2(int x, int tp){
top[x] = tp, dfn[x] = ++cnt, pre[cnt] = x;
if(son[x]) dfs2(son[x], tp);
for(int i = head[x]; i; i = e[i].nxt){
int v = e[i].to;
if(v == fath[x] || v == son[x]) continue;
dfs2(v, v);
}
}
void change(int k, int w){
int ee = k * 2 - 1;
int x = e[ee].to, y = e[ee + 1].to;
if(fath[x] == y) Seg::cover(1, 1, n, dfn[x], dfn[x], w);
else Seg::cover(1, 1, n, dfn[y], dfn[y], w);
}
void change_add(int x, int y, int k){
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
Seg::add(1, 1, n, dfn[top[x]], dfn[x], k);
x = fath[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
Seg::add(1, 1, n, dfn[x] + 1, dfn[y], k);
return ;
}
void change_cover(int x, int y, int k){
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
Seg::cover(1, 1, n, dfn[top[x]], dfn[x], k);
x = fath[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
Seg::cover(1, 1, n, dfn[x] + 1, dfn[y], k);
return ;
}
int ask(int x, int y){
int maxn = -1e9 + 7;
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) swap(x, y);
maxn = max(maxn, Seg::get_max(1, 1, n, dfn[top[x]], dfn[x]));
x = fath[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
maxn = max(maxn, Seg::get_max(1, 1, n, dfn[x] + 1, dfn[y]));
return maxn;
}
}
signed main()
{
n = read();
for(int i = 1, u, v, w; i <= n - 1; ++i){
u = read(), v = read(), w = read();
Cut::add(u, v, w),Cut::add(v, u, w);
}
Cut::dfs(1, 0), Cut::dfs2(1, 1), Seg::build(1, 1, n);
while(1){
int x, y, w, k;
cin>>s;
if(s[1] == 'a'){//max
x = read(), y = read();
printf("%d\n", Cut::ask(x, y));
}
if(s[1] == 'o'){//cover
x = read(), y = read(), w = read();
Cut::change_cover(x, y, w);
}
if(s[1] == 'd'){//add
x = read(), y = read(), k = read();
Cut::change_add(x, y, k);
}
if(s[1] == 'h'){//change
k = read(), w = read();
Cut::change(k, w);
}
if(s[1] == 't'){//stop
return 0;
}
}
}