rt
#include<bits/stdc++.h>
#define PII pair<int, int>
#define fst first
#define scd second
#define int long long
#define l(u) u << 1
#define r(u) u << 1 | 1
#define FH signed
using namespace std;
const int N = 1e5 + 10;
PII edge[N];
int d[N], f[N], siz[N], son[N], top[N], a[N], id[N], wc[N], cnt;
vector<PII> e[N];
struct node
{
int l, r;
int maxx;
int add, cov;
} tr[N * 4];
void dfs1(int u, int fa, int dep)
{
d[u] = dep;
f[u] = fa;
siz[u] = 1;
int maxx = 0;
for(auto v : e[u])
{
if(v.fst == fa) continue;
dfs1(v.fst, u, dep + 1);
a[v.fst] = v.scd;
siz[u] += siz[v.fst];
if(maxx < siz[v.fst])
maxx = siz[v.fst], son[u] = v.fst;
}
}
void dfs2(int u, int t)
{
id[u] = ++ cnt;
wc[cnt] = a[u];
top[u] = t;
if(!son[u]) return ;
dfs2(son[u], t);
for(auto v : e[u])
{
if(v.fst == son[u] || v.fst == f[u]) continue;
dfs2(v.fst, v.fst);
}
}
void pushup(int u)
{
tr[u].maxx = max(tr[l(u)].maxx, tr[r(u)].maxx);
}
void pushdown(int u)
{
if(tr[u].cov != -1)
tr[l(u)].maxx = tr[r(u)].maxx = tr[u].cov,
tr[l(u)].cov = tr[r(u)].cov = tr[u].cov;
tr[l(u)].maxx += tr[u].add;
tr[r(u)].maxx += tr[u].add;
tr[l(u)].add += tr[u].add;
tr[r(u)].add += tr[u].add;
tr[u].cov = -1, tr[u].add = 0;
}
void build(int u, int l ,int r)
{
tr[u] = {l, r, 0, 0, -1};
if(l == r)
{
tr[u].maxx = wc[l];
return ;
}
int mid = l + r >> 1;
build(l(u), l, mid);
build(r(u), mid + 1, r);
pushup(u);
}
void modify(int u, int l, int r, int cov, int add)
{
if(l <= tr[u].l && tr[u].r <= r)
{
if(cov != -1)
tr[u].maxx = tr[u].cov = cov,
tr[u].add = 0;
tr[u].maxx += add;
tr[u].add += add;
return ;
}
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
if(l <= mid) modify(l(u), l, r, cov, add);
if(r > mid) modify(r(u), l, r, cov, add);
pushup(u);
}
void modify(int u, int x, int cov, int add)
{
if(tr[u].l == tr[u].r)
{
if(cov != -1)
tr[u].maxx = tr[u].cov = cov,
tr[u].add = 0;
tr[u].maxx += add;
tr[u].add += add;
return ;
}
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
if(x <= mid) modify(l(u), x, cov, add);
else modify(r(u), x, cov, add);
pushup(u);
}
int query(int u, int l, int r)
{
if(l <= tr[u].l && tr[u].r <= r)
return tr[u].maxx;
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1, res = 0;
if(l <= mid) res = max(res, query(l(u), l, r));
if(r > mid) res = max(res, query(r(u), l, r));
return res;
}
void modify_range(int x, int y, int cov, int add)
{
while(top[x] != top[y])
{
if(d[top[x]] < d[top[y]]) swap(x, y);
modify(1, id[top[x]], id[x], cov, add);
x = f[top[x]];
}
if(d[x] > d[y]) swap(x, y);
modify(1, id[x] + 1, id[y], cov, add);
}
int query_range(int x, int y)
{
int res = 0;
while(top[x] != top[y])
{
if(d[top[x]] < d[top[y]]) swap(x, y);
res = max(res, query(1, id[top[x]], id[x]));
x = f[top[x]];
}
if(d[x] > d[y]) swap(x, y);
res = max(res, query(1, id[x] + 1, id[y]));
return res;
}
FH main()
{
// ios::sync_with_stdio(0);
// cin.tie(0);
// cout.tie(0);
int n;
cin >> n;
for(int i = 1; i < n; i ++)
{
int a, b, c;
cin >> a >> b >> c;
e[a].push_back({b, c});
e[b].push_back({a, c});
edge[i] = {a, b};
}
dfs1(1, 0, 1);
dfs2(1, 1);
build(1, 1, n);
while(1)
{
string opt;
cin >> opt;
if(opt[0] == 'S') break;
int k, u, v, w;
if(opt[1] == 'h')
{
cin >> k >> w;
if (d[edge[k].fst] > d[edge[k].scd]) k = edge[k].fst;
else k = edge[k].scd;
modify(1, id[k], w, 0);
}
if(opt[1] == 'o')
{
cin >> u >> v >> w;
modify_range(u, v, w, 0);
}
if(opt[1] == 'd')
{
cin >> u >> v >> w;
modify_range(u, v, -1, w);
}
if(opt[1] == 'a')
{
cin >> u >> v;
cout << query_range(u, v) << "\n";
}
}
return 0;
}