#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef long long ll;
const int MAX = 1e6 + 10;
int n, m;
int w[MAX];
int from, to;
int op, x, a;
int t1[MAX << 2], t2[MAX << 2];
vector <int > edge[MAX];
namespace BIT {
inline int lowbit(int x) {
return x & (-x);
}
inline void add1(int x, int k) {
for (int i = x; i <= n; i += lowbit(i)) {
t1[i] += k;
t2[i] += k * x;
}
}
inline void add(int l, int r, int k) {
add1(l, k);
add1(r + 1, -k);
}
inline int query1(int x) {
ll res = 0;
for (int i = x; i; i -= lowbit(i)) {
res += t1[i] * (x + 1);
res -= t2[i];
}
return res;
}
inline int query(int l, int r) {
return query1(r) - query1(l - 1);
}
}
int fa[MAX], dep[MAX], size[MAX], son[MAX], id[MAX], top[MAX];
int cnt;
namespace dfs {
void dfs1(int now, int f) {
fa[now] = f;
dep[now] = dep[f] + 1;
size[now] = 1;
int maxson = -1;
for (auto &&e : edge[now]) {
if (e == f) continue;
size[now] += size[e];
if (size[e] > maxson) {
maxson = size[e];
son[now] = e;
}
}
}
void dfs2(int now, int tp) {
top[now] = tp;
id[now] = ++cnt;
if (w[now]) BIT::add(id[now], id[now], w[now]);
if (!son[now]) return;
dfs2(son[now], tp);
for (auto &&e : edge[now]) {
if (e == son[now] or e == fa[now]) continue;
dfs2(e, e);
}
}
}
namespace yuanshen {
void addpoint(int x, int k) {
BIT::add(id[x], id[x], k);
}
void addsub(int x, int k) {
BIT::add(id[x], id[x] + size[x] - 1, k);
}
int queryPath(int u, int v) {
int res = 0;
while (top[v] != top[u]) {
if (dep[top[u]] < dep[top[v]]) swap(u, v);
res = (res + BIT::query(id[top[u]], id[u]));
u = fa[top[u]];
}
if (dep[u] > dep[v]) swap(u, v);
res = (res + BIT::query(id[u], id[v]));
return res;
}
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
for (register int i = 1; i <= n; i++) cin >> w[i];
for (register int i = 1; i < n; i++) {
cin >> from >> to;
edge[from].push_back(to);
edge[to].push_back(from);
}
dfs::dfs1(1, 0);
dfs::dfs2(1, 1);
while (m--) {
cin >> op;
if (op == 1) {
cin >> x >> a;
yuanshen::addpoint(x, a);
} else if (op == 2) {
cin >> x >> a;
yuanshen::addsub(x, a);
} else {
cin >> x;
cout<<yuanshen::queryPath(1,x)<<'\n';
}
}
return 0;
}