#include<stdio.h>
#define N 100009
struct Splay
{
int rt, tot, cnt[N], val[N], fa[N], ch[N][2], siz[N];
inline void updata(int x)
{
siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + cnt[x];
}
inline bool get(int x)
{
return x == ch[fa[x]][1];
}
inline void clear(int x)
{
cnt[x] = val[x] = fa[x] = ch[x][0] = ch[x][1] = siz[x] = 0;
}
inline void rorate(int x)
{
int y = fa[x], z = fa[y], f = get(x);
ch[y][f] = ch[x][!f];
if (ch[x][!f])
fa[ch[x][!f]] = y;
ch[x][!f] = y;
fa[y] = x;
fa[x] = z;
if (z)
ch[z][y == ch[z][1]] = x;
updata(x), updata(y);
}
inline void splay(int x, int root = 0)
{
while (fa[x] != root)
{
rorate(x);
}
if (!root)
rt = x;
}
inline void insert(int x)
{
if (!rt)
{
rt = ++ tot;
val[tot] = x;
cnt[tot] = 1;
updata(rt);
return;
}
int cur = rt, f = 0;
while (1)
{
if (val[cur] == x)
{
cnt[cur] ++;
updata(cur);
updata(f);
splay(cur);
return;
}
f = cur;
cur = ch[cur][val[cur] < x];
if (!cur)
{
ch[f][val[f] < x] = ++ tot;
fa[tot] = f;
val[tot] = x;
cnt[tot] = 1;
updata(tot);
updata(f);
splay(tot);
return;
}
}
}
inline int nxt()
{
int cur = ch[rt][1];
if (!cur)
return cur;
while (ch[cur][0])
cur = ch[cur][0];
splay(cur);
return cur;
}
inline int pre()
{
int cur = ch[rt][0];
if (!cur)
return cur;
while (ch[cur][1])
cur = ch[cur][1];
splay(cur);
return cur;
}
inline int rank(int x)
{
int cur = rt, ret = 0;
while (cur)
{
if (x < val[cur])
cur = ch[cur][0];
else
{
ret += siz[ch[cur][0]];
if (x == val[cur])
{
splay(cur);
return ret + 1;
}
ret += cnt[cur];
cur = ch[cur][1];
}
}
}
inline void del(int x)
{
rank(x);
if (cnt[rt] > 1)
{
cnt[rt] --, siz[rt] --;
return;
}
if (!ch[rt][0] && !ch[rt][1])
{
clear(rt);
rt = 0;
return;
}
if (!ch[rt][0])
{
int cur = rt;
rt = ch[rt][1];
fa[rt] = 0;
clear(cur);
return;
}
if (!ch[rt][1])
{
int cur = rt;
rt = ch[rt][0];
fa[rt] = 0;
clear(cur);
return;
}
int cur = rt, k = pre();
fa[ch[cur][1]] = k;
ch[k][1] = ch[cur][1];
clear(cur);
updata(rt);
}
inline int xrank(int x)
{
int cur = rt;
while (1)
{
if (ch[cur][0] && x <= siz[ch[cur][0]])
cur = ch[cur][0];
else
{
x -= siz[ch[cur][0]] + cnt[cur];
if (x <= 0)
{
splay(cur);
return val[cur];
}
cur = ch[cur][1];
}
}
}
}T;
int a[N], rt;
struct node
{
int v, nxt;
}e[N << 1];
int head[N], cnt;
int dfn[N], tot[N], b[N], deep[N], top[N], fa[N], siz[N], hson[N];
void dfs1(int u, int fath)
{
fa[u] = fath;
deep[u] = deep[fath] + 1;
siz[u] = 1;
hson[u] = -1;
for (int i = head[u];i;i = e[i].nxt)
if (e[i].v != fath)
{
dfs1(e[i].v, u);
siz[u] += siz[e[i].v];
if (hson[u] == -1 || siz[e[i].v] > siz[hson[u]])
hson[u] = e[i].v;
}
}
void dfs2(int u, int Top)
{
top[u] = Top;
dfn[u] = ++ cnt;
b[cnt] = a[u];
if (hson[u] == -1)
return;
dfs2(hson[u], Top);
for (int i = head[u];i;i = e[i].nxt)
if (e[i].v != hson[u] && e[i].v != fa[u])
dfs2(e[i].v, e[i].v);
}
inline void add(int u, int v)
{
e[++ cnt].v = v, e[cnt].nxt = head[u], head[u]= cnt;
}
int tree[N << 2], lazy[N << 2];
#define ls (p << 1)
#define rs (ls + 1)
void build(int l, int r, int p)
{
if (l == r)
{
tree[p] = b[l];
return;
}
int mid = (l + r) >> 1;
build(l, mid, ls);
build(mid + 1, r, rs);
tree[p] = tree[ls] + tree[rs];
}
inline void pushdown(int l, int r, int p)
{
lazy[ls] += lazy[p];
lazy[rs] += lazy[p];
int mid = (l + r) >> 1;
tree[ls] += lazy[ls] * (mid - l + 1);
tree[rs] += lazy[rs] * (r - mid);
}
void change(int sl, int sr, int l, int r, int p, int k)
{
if (l >= sl && r <= sr)
{
tree[p] += (r - l + 1) * k;
lazy[p] += k;
return;
}
pushdown(l, r, p);
int mid = (l + r) >> 1;
if (sl <= mid)
change(sl, sr, l, mid, ls, k);
if (sr > mid)
change(sl, sr, mid + 1, r, rs, k);
tree[p] = tree[ls] + tree[rs];
}
int query(int sl, int sr, int l, int r, int p)
{
if (l >= sl && r <= sr)
return tree[p];
pushdown(l, r, p);
int mid = (l + r) >> 1, ret = 0;
if (sl <= mid)
ret = query(sl, sr, l, mid, ls);
if (sr > mid)
ret += query(sl, sr, mid + 1, r, rs);
return ret;
}
int n;
inline void swap(int& a, int& b) {a ^= b, b ^= a, a ^= b;}
inline void Change(int u, int A)
{
change(u, u, 1, n, 1, A);
}
inline void Change1(int u, int A)
{
change(dfn[u], dfn[u] + siz[u] - 1, 1, n, 1, A);
}
inline void Query(int u)
{
int ans = 0;
int v = 1;
while (top[u] != top[v])
{
if (deep[u] < deep[v])
swap(u, v);
ans += query(dfn[top[u]], dfn[u], 1, n, 1);
u = fa[top[u]];
}
if (dfn[u] > dfn[v])
swap(u, v);
printf("%d\n", ans + query(dfn[u], dfn[v], 1, n, 1));
}
int main()
{
int m;
scanf("%d%d", &n, &m);
for (int i = 1;i <= n;i ++)
scanf("%d", &a[i]);
int u, v;
for (int i = 1;i < n;i ++)
scanf("%d%d", &u, &v), add(u, v), add(v, u);
dfs1(1, 0);
dfs2(1, 1);
build(1, n, 1);
int opt;
while (m --)
{
scanf("%d%d", &opt, &u);
if (opt == 1)
scanf("%d", &v), Change(u, v);
if (opt == 2)
scanf("%d", &v), Change1(u, v);
if (opt == 3)
Query(u);
}
return 0;
}