#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 10;
int n, m, rt, mod, cnt, tp, ans, a[N], fa[N], Head[N << 1], to[N << 1], nex[N << 1], son[N], siz[N], dfn[N], rnk[N], dep[N], top[N], tre[N << 2], lazy[N << 2], dir[N << 2];
inline int read()
{
int r = 0, w = 1;
char ch = getchar();
while (!isdigit(ch))
{
if (ch == '-')
w = -1;
ch = getchar();
}
while (isdigit(ch))
{
r = (r << 3) + (r << 1) + (ch ^ 48);
ch = getchar();
}
return r * w;
}
void add(int x, int y)
{
nex[++ cnt] = Head[x];
Head[x] = cnt;
to[cnt] = y;
}
void dfs1(int u, int f)
{
son[u] = -1;//初始化无重儿子
siz[u] = 1;
for (int i = Head[u]; i ; i = nex[i])
{
int v = to[i];
if(v ^ f)
{
dep[v] = dep[u] + 1;
fa[v] = u;
dir[i / 2] = v;
dfs1(v, u);
siz[u] += siz[v];
if (son[u] == -1 || siz[v] > siz[son[u]]) son[u] = v;
}
}
}
void dfs2(int x, int fath)
{
top[x] = fath;
dfn[x] = ++ tp;
rnk[tp] = x;
if (son[x] == -1) return;//叶子节点
dfs2 (son[x], fath);
for (int i = Head[x]; i ; i = nex[i])
{
int v = to[i];
if (v != fa[x] && v != son[x]) dfs2(v, v);
}
}
void pushup(int x)
{
tre[x] = (tre[x << 1] + tre[x << 1 | 1]) % mod;
}
void pushdown(int x, int l, int r)
{
if (lazy[x])
{
lazy[x << 1] += lazy[x];
lazy[x << 1 | 1] += lazy[x];
tre[x << 1] += lazy[x] * ((r - l + 1) - ((r - l + 1) >> 1));
tre[x << 1] %= mod;
tre[x << 1 | 1] += lazy[x] * ((r - l + 1) >> 1);
tre[x << 1 | 1] %= mod;
lazy[x] = 0;
}
return;
}
void build(int x, int l, int r)
{
if (!(l ^ r))
{
tre[x] = a[rnk[l]] % mod;
return;
}
int mid = l + r >> 1;
build(x << 1, l, mid);
build(x << 1 | 1, mid + 1, r);
pushup(x);
}
void update(int x, int l, int r, int u, int v, int w)
{
if (u <= l && r <= v)
{
lazy[x] += w;
tre[x] += w * (r - l + 1);
tre[x] %= mod;
return;
}
int mid = l + r >> 1;
if (u <= mid) update(x << 1, l, mid, u, v, w);
if (v > mid) update(x << 1 | 1, mid + 1, r, u, v, w);
pushup(x);
}
void query (int x, int l, int r, int u, int v)
{
if (!(l ^ r))
{
ans += tre[x];
ans %= mod;
return;
}
int mid = l + r >> 1;
pushdown(x, l, r);
if (u <= mid) query(x << 1, l, mid, u, v);
if (v > mid) query(x << 1 | 1, mid + 1, r, u, v);
}
void zsupdate(int x, int w)
{
update (1, 1, n, dfn[x], dfn[x] + siz[x] - 1, w);
}
int fastquery(int x, int y)
{
int res = 0;
while (top[x] ^ top[y])
{
if (dep[top[x]] < dep[top[y]])
{
swap(x, y);
}
ans = 0;
query(1, 1, n, dfn[top[x]], dfn[x]);
res = (res + ans) % mod;
x = fa[top[x]];
}
if (dep[x] > dep[y]) swap(x, y);
ans = 0;
query(1, 1, n, dfn[x], dfn[y]);
res = (res + ans) % mod;
return res;
}
signed main()
{
n = read();
m = read();
mod = 1e18;
for (int i = 1;i <= n; ++ i)
{
a[i] = read();
}
for (int i = 1; i < n; ++ i)
{
int u = read(), v = read();
add(u, v);
add(v, u);
}
dfs1 (1, 0);
dfs2 (1, 1);
build (1, 1, n);
while (m --)
{
int op = read();
if (op == 1)
{
int x = read(), w = read();
update(1, 1, n, dfn[x], dfn[x], w);
}
else if (op == 2)
{
int x = read(), y = read();
zsupdate (x, y);
}
else
{
int x = read();
printf("%lld\n", fastquery(1, x));
}
}
return 0;
}
TLE 50,感觉不应该超时吧。