#include <bits/stdc++.h>
using namespace std;
typedef vector<int> vi;
const int NN = 1e5 + 4;
int T[NN];
struct LCA {
static const int HH = 18;
int timer = 0, Tin[NN], fa[HH][NN], Dep[NN];
vi G[NN], W[NN];
vector<pair<int, int>> X[NN];
void addEdge(int u, int v) { G[u].push_back(v), G[v].push_back(u); }
void dfs(int u, int f) {
auto &w = W[T[u]];
auto &x = X[T[u]];
w.push_back(u), x.push_back({Tin[u] = timer++, u});
fa[0][u] = f, Dep[u] = Dep[f] + 1;
for (int k = 1; k < HH; ++k) fa[k][u] = fa[k - 1][fa[k - 1][u]];
for (int v : G[u])
if (v != f) dfs(v, u);
w.pop_back(), x.push_back({timer, !w.empty() ? w.back() : 0});
}
int lca(int u, int v) {
if (Dep[u] < Dep[v]) swap(u, v);
for (int k = HH - 1; k >= 0; --k)
if ((Dep[u] - Dep[v]) & (1 << k)) u = fa[k][u];
for (int k = HH - 1; k >= 0; --k)
if (fa[k][u] != fa[k][v]) u = fa[k][u], v = fa[k][v];
return u == v ? u : fa[0][u];
}
int last(int u, int c) {
auto &x = X[c];
auto it = upper_bound(begin(x), end(x), make_pair(Tin[u], NN + 10));
return it == begin(x) ? 0 : prev(it)->second;
}
} L;
int solve(int u, int v, int c) {
int d = L.lca(u, v), a = L.last(u, c);
if (a && L.Dep[a] >= L.Dep[d]) return 1;
a = L.last(v, c);
return a && L.Dep[a] >= L.Dep[d];
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int N, M;
cin >> N >> M;
for (int i = 1; i <= N; ++i) cin >> T[i];
for (int i = 1, u, v; i < N; ++i) cin >> u >> v, L.addEdge(u, v);
L.dfs(1, 0);
for (int i = 0, A, B, C; i < M; ++i)
cin >> A >> B >> C, cout << solve(A, B, C);
cout << endl;
}
#include <bits/stdc++.h>
using namespace std;
struct Edge {
int v, w;
};
typedef vector<int> vi;
const int VV = 1e6 + 4, INF = 1e9;
vi G[VV];
vector<Edge> Es;
void addEdge(int u, int v, int w) {
G[u].push_back(Es.size()), Es.push_back({v, w});
}
int Sz[VV], Pw[VV], timer;
int Pre[VV], B[VV], D[VV], Tin[VV], Tout[VV];
struct SegTree {
int minv[VV], addv[VV];
inline void maintain(int o) { minv[o] = min(minv[2 * o], minv[2 * o + 1]); }
void build(int o, int L, int R) {
if (L == R) {
minv[o] = B[Pre[L]] + D[Pre[L]];
return;
}
int lc = 2 * o, rc = 2 * o + 1, m = (L + R) / 2;
build(lc, L, m), build(rc, m + 1, R), maintain(o);
}
inline void pushdown(int o) {
int &a = addv[o], lc = 2 * o, rc = 2 * o + 1;
if (a == 0) return;
addv[lc] += a, addv[rc] += a, minv[lc] += a, minv[rc] += a;
a = 0;
}
int querymin(int o, int L, int R, int ql, int qr) {
int lc = 2 * o, rc = 2 * o + 1, m = (L + R) / 2;
if (L > qr || R < ql) return INF;
if (L >= ql && R <= qr) return minv[o];
pushdown(o);
return min(querymin(lc, L, m, ql, qr), querymin(rc, m + 1, R, ql, qr));
}
void add(int o, int L, int R, int ql, int qr, int v) {
if (L > qr || R < ql) return;
if (L >= ql && R <= qr) return (void)(minv[o] += v, addv[o] += v);
int lc = 2 * o, rc = 2 * o + 1, m = (L + R) / 2;
pushdown(o);
add(lc, L, m, ql, qr, v), add(rc, m + 1, R, ql, qr, v);
maintain(o);
}
};
void dfs(int u, int fa) {
Tin[u] = ++timer, Pre[timer] = u;
for (int ei : G[u]) {
const Edge &e = Es[ei];
if (e.v == fa) continue;
D[e.v] = D[u] + e.w, Pw[e.v] = e.w, dfs(e.v, u);
}
Tout[u] = timer;
}
SegTree S;
int N, M;
inline int getD(int x) { return S.querymin(1, 1, N, Tin[x], Tin[x]) - B[x]; }
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> N >> M;
for (int i = 1, u, v, w; i < N; ++i) cin >> u >> v >> w, addEdge(u, v, w);
vi E(2 * N);
for (int i = N, u, v, w; i <= 2 * N - 2; ++i)
cin >> u >> v >> w, B[u] = w, E[i] = u;
dfs(1, 0), S.build(1, 1, N);
while (M--) {
int o, i, w, u, v;
cin >> o;
if (o == 1) {
cin >> i >> w;
if (i >= N)
u = E[i], S.add(1, 1, N, Tin[u], Tin[u], w - B[u]), B[u] = w;
else
u = Es[i - 1].v, S.add(1, 1, N, Tin[u], Tout[u], w - Pw[u]), Pw[u] = w;
} else {
cin >> u >> v;
if (Tin[u] <= Tin[v] && Tin[v] <= Tout[u])
cout << getD(v) - getD(u) << endl;
else
cout << S.querymin(1, 1, N, Tin[u], Tout[u]) - getD(u) + getD(v)
<< endl;
}
}
}