#include <iostream>
using std::cin;
using std::cout;
using std::cerr;
using std::endl;
#include <vector>
using std::vector;
using std::pair;
#include <algorithm>
using std::sort;
using std::max;
using std::min;
using std::reverse;
#include <set>
using std::set;
typedef long long int ll;
typedef pair<ll, ll> P;
const ll INF = 1'000'000'000'009;
ll n, q;
ll a[300'000], b[300'000], c[300'000], d[300'000];
ll qt[300'000], qi[300'000], qx[300'000];
vector<P> g[300'000];
typedef struct {
ll chl;
ll chr;
ll add;
} segnode;
ll operate (segnode f, ll x) {
return min(max(x, f.chl), f.chr) + f.add;
}
const segnode unity = {0, INF, 0};
// merge of parent node (r) and child node (l)
segnode merge (segnode r, segnode l) {
segnode res;
ll cll = l.chl;
ll clr = l.chr;
ll crl = r.chl - l.add;
ll crr = r.chr - l.add;
res.add = l.add + r.add;
ll ml, mr;
if (clr < crl) {
ml = mr = crl;
} else if (crr < cll) {
ml = mr = crr;
} else {
ml = max(cll, crl);
mr = min(clr, crr);
}
res.chl = ml;
res.chr = mr;
return res;
}
const ll base = 1 << 19;
segnode seg[1 << 20];
void seg_init (void) {
for (ll i = 0; i < base * 2; i++) {
seg[i] = unity;
}
}
void seg_set (ll v, segnode x) {
seg[v += base] = x;
while (v /= 2) {
seg[v] = merge(seg[v * 2 + 0], seg[v * 2 + 1]);
}
}
segnode seg_find (ll l, ll r) {
segnode suml = unity, sumr = unity;
for ((l += base), (r += base); l < r; (l /= 2), (r /= 2)) {
if (l % 2) {
suml = merge(suml, seg[l++]);
}
if (r % 2) {
sumr = merge(seg[--r], sumr);
}
}
return merge(suml, sumr);
}
ll subsize[300'000]; // size of subtree
ll par[300'000]; // parent node (par[0] = 0)
ll upedge[300'000]; // edge leading to parent (upedge[0] = -1)
ll size_dfs (ll v, ll p) {
subsize[v] = 1;
for (auto &[u, e] : g[v]) {
if (u == p) continue;
par[u] = v;
upedge[u] = e;
subsize[v] += size_dfs(u, v);
}
return subsize[v];
}
void size_init () {
par[0] = 0;
upedge[0] = -1;
size_dfs(0, n);
}
ll hlpar[300'000]; // top vertex of HL component v belongs
ll hlbottom[300'000]; // bottom vertex of HL component v belongs
ll heavy[300'000]; // heavy child (-1 for leaf)
vector<ll> hleuler; // HL euler tour
ll vtohl[300'000]; // hleuler[vtohl[v]] == v
void hl_dfs (ll v, ll p) {
hleuler.push_back(v);
vtohl[v] = hleuler.size() - 1;
heavy[v] = -1;
ll heavysize = 0;
for (auto &[u, e] : g[v]) {
if (u == p) continue;
if (subsize[u] > heavysize) {
heavysize = subsize[u];
heavy[v] = u;
}
}
if (heavy[v] == -1) {
hlbottom[v] = v;
return;
}
hlpar[heavy[v]] = hlpar[v];
hl_dfs(heavy[v], v);
hlbottom[v] = hlbottom[heavy[v]];
for (auto &[u, e] : g[v]) {
if (u == p) continue;
if (u == heavy[v]) continue;
hlpar[u] = u;
hl_dfs(u, v);
}
}
void hl_init () {
size_init();
hlpar[0] = 0;
hl_dfs(0, n);
}
vector<P> hl_divide (ll v) {
vector<P> vec;
while (true) {
ll p = hlpar[v];
vec.push_back({p, v});
if (p == 0) break;
v = par[p];
}
reverse(vec.begin(), vec.end());
return vec;
}
typedef struct {
int32_t l;
int32_t r;
int32_t p;
int32_t val;
} sparsenode;
vector<sparsenode> sparseseg;
int32_t roots[300'000];
const ll DEPTH = 60;
int32_t sparse_newroot (void) {
int32_t idx = sparseseg.size();
sparseseg.push_back((sparsenode){-1,-1,idx,0});
return idx;
}
int32_t sparse_newnode (int32_t p) {
int32_t idx = sparseseg.size();
sparseseg.push_back((sparsenode){-1,-1,p,0});
return idx;
}
void sprase_init (ll n) {
for (ll i = 0; i < n; i++) {
roots[i] = sparse_newroot();
}
}
ll sparse_select (int32_t r, int32_t k) {
ll ans = 0;
ll curr = r;
int32_t kc = k;
for (ll i = DEPTH - 1; i >= 0; i--) {
bool isr;
int32_t minus;
if (sparseseg[curr].l == -1) {
// right
minus = 0;
isr = true;
} else if (sparseseg[curr].r == -1) {
// left
minus = 0;
isr = false;
} else {
if (sparseseg[sparseseg[curr].l].val < kc) {
minus = sparseseg[sparseseg[curr].l].val;
isr = true;
} else {
minus = 0;
isr = false;
}
}
if (isr) {
ans |= (1LL << i);
kc -= minus;
curr = sparseseg[curr].r;
} else {
ans |= 0;
kc -= 0;
curr = sparseseg[curr].l;
}
}
return ans;
}
int32_t sparse_access (int32_t r, ll u) {
int32_t curr = r;
for (ll i = DEPTH - 1; i >= 0; i--) {
if (u & (1LL << i)) {
// right
if (sparseseg[curr].r == -1) {
sparseseg[curr].r = sparse_newnode(curr);
}
curr = sparseseg[curr].r;
} else {
// left
if (sparseseg[curr].l == -1) {
sparseseg[curr].l = sparse_newnode(curr);
}
curr = sparseseg[curr].l;
}
}
return curr;
}
void addchild (ll v, ll u, int32_t x) {
int32_t curr = sparse_access(roots[v], u);
while (true) {
sparseseg[curr].val += x;
if (curr == roots[v]) break;
curr = sparseseg[curr].p;
}
}
ll find_kth (ll v, ll k) {
if (k <= 0) {
return 0;
} else if (sparseseg[roots[v]].val < k) {
return INF;
} else {
return sparse_select(roots[v], k);
}
}
ll top_uproot[300'000];
segnode op_check (ll v) {
ll upadd;
if (heavy[v] == -1) {
upadd = INF;
} else {
upadd = d[upedge[heavy[v]]];
}
ll downadd;
if (v == 0) {
downadd = INF;
} else {
downadd = d[upedge[v]];
}
ll ml, mr;
ml = find_kth(v, c[v] - 1);
mr = find_kth(v, c[v]);
segnode sn_up;
sn_up.add = upadd;
sn_up.chl = ml - sn_up.add;
sn_up.chr = mr - sn_up.add;
seg_set(vtohl[v], sn_up);
segnode sn_down;
sn_down.add = downadd;
sn_down.chl = ml - sn_down.add;
sn_down.chr = mr - sn_down.add;
seg_set(base - 1 - vtohl[v], sn_down);
return sn_up;
}
ll uproot (ll root) {
ll bottom = hlbottom[root];
segnode op = seg_find(vtohl[root], vtohl[bottom] + 1);
return operate(op, INF);
}
void segvalue_dfs (ll v, ll p) {
if (heavy[v] != -1) {
segvalue_dfs(heavy[v], v);
}
for (auto &[u, e] : g[v]) {
if (u == p) continue;
if (u == heavy[v]) continue;
segvalue_dfs(u, v);
}
// postorder
for (auto &[u, e] : g[v]) {
if (u == p) continue;
if (u == heavy[v]) continue;
ll cval = top_uproot[u] + d[upedge[u]];
addchild(v, cval, +1);
}
segnode sn = op_check(v);
if (v == 0 || hlpar[v] == v) {
top_uproot[v] = uproot(v);
}
}
void segvalue_init () {
sprase_init(n);
segvalue_dfs(0, n);
}
void kth_replace (ll v, P pold, P pnew) {
addchild(v, pold.first, -1);
addchild(v, pnew.first, +1);
}
void climb_uproot (ll v) {
ll curr = v;
while (true) {
ll p = hlpar[curr];
ll pup = uproot(p);
ll pval_old = top_uproot[p] + d[upedge[p]];
top_uproot[p] = pup;
ll pval_new = top_uproot[p] + d[upedge[p]];
if (p == 0) break;
kth_replace(par[p], {pval_old, p}, {pval_new, p});
segnode newnode = op_check(par[p]);
curr = par[p];
}
}
void edge_change (ll e, ll x) {
ll v = a[e], u = b[e];
if (par[v] == u) {
ll t = v;
v = u;
u = t;
}
// par[u] == v
if (hlpar[u] == hlpar[v]) {
d[e] = x;
} else {
ll cval_old = top_uproot[u] + d[e];
d[e] = x;
ll cval_new = top_uproot[u] + d[e];
kth_replace(v, {cval_old, u}, {cval_new, u});
}
op_check(u);
op_check(v);
climb_uproot(v);
}
void vertex_change (ll v, ll x) {
c[v] = x;
segnode newnode = op_check(v);
climb_uproot(v);
}
segnode revseg_find (ll l, ll r) {
return seg_find(base - r, base - l);
}
ll stepdown (ll v, ll t) {
ll tup = t + d[upedge[v]];
vector<ll> addlist;
addlist.push_back(tup);
if (heavy[v] != -1) {
addlist.push_back(uproot(heavy[v]) + d[upedge[heavy[v]]]);
}
for (ll x : addlist) {
addchild(v, x, +1);
}
ll tans = find_kth(v, c[v]);
for (ll x : addlist) {
addchild(v, x, -1);
}
return tans;
}
ll ask (ll v) {
ll t0 = uproot(0);
vector<P> roads = hl_divide(v);
ll t = t0;
for (ll i = 0; i < roads.size(); i++) {
ll l = vtohl[roads[i].first];
ll r = vtohl[roads[i].second];
ll curri = l;
if (l + 1 <= r - 1) {
segnode sn = revseg_find(l + 1, r - 1 + 1);
t = operate(sn, t);
curri = r - 1;
}
while (curri < r) {
++curri;
ll currv = hleuler[curri];
t = stepdown(currv, t);
}
if (i + 1 < roads.size()) {
t = stepdown(roads[i + 1].first, t);
}
}
return t;
}
void solve () {
seg_init();
hl_init();
segvalue_init();
for (ll i = 0; i < q; i++) {
if (qt[i] == 1) {
// v c
ll v = qi[i];
vertex_change(v, qx[i]);
c[v] = qx[i];
} else if (qt[i] == 2) {
// e d
ll e = qi[i];
edge_change(e, qx[i]);
} else {
// v ?
ll ans = ask(qi[i]);
if (ans >= INF) {
ans = -1;
}
cout << ans << "\n";
}
}
}
int main (void) {
cin.tie(nullptr);
std::ios_base::sync_with_stdio(false);
cin >> n;
for (ll i = 0; i < n - 1; i++) {
cin >> a[i] >> b[i] >> d[i];
a[i]--;
b[i]--;
// rev
a[i] = n - 1 - a[i];
b[i] = n - 1 - b[i];
}
for (ll i = 0; i < n; i++) {
ll x;
cin >> x;
// rev
c[n - 1 - i] = x;
}
cin >> q;
for (ll i = 0; i < q; i++) {
cin >> qt[i];
if (qt[i] == 1 || qt[i] == 2) {
cin >> qi[i] >> qx[i];
} else {
cin >> qi[i];
}
qi[i]--;
// rev
if (qt[i] == 1 || qt[i] == 3) {
qi[i] = n - 1 - qi[i];
}
}
for (ll i = 0; i < n - 1; i++) {
g[a[i]].emplace_back(b[i], i);
g[b[i]].emplace_back(a[i], i);
}
solve();
return 0;
}