#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
const int N = 100010, M = 200010;
int n, m;
int w[N], new_w[N];
int id[N], cnt;
int depth[N], fa[N], son[N], sz[N], top[N];
int h[N], e[M], ne[M], idx;
struct node {
int l, r;
int xsum;
} tr[N << 2];
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
void dfs1(int u, int p, int dep)
{
depth[u] = dep, fa[u] = p, sz[u] = 1;
for(int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
if(j == p) continue;
dfs1(j, u, dep + 1);
sz[u] += sz[j];
if(sz[son[u]] < sz[j]) son[u] = j;
}
}
void dfs2(int u, int t)
{
top[u] = t, id[u] = ++ cnt, new_w[cnt] = w[u];
if(son[u] == 0) return;
dfs2(son[u], t);
for(int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
if(j == fa[u] || j == son[u]) continue;
dfs2(j, j);
}
}
void pushup(int u)
{
tr[u].xsum = tr[u << 1].xsum ^ tr[u << 1 | 1].xsum;
}
void build(int u, int l, int r)
{
if(l >= r) tr[u] = {l, r, new_w[r]};
else
{
tr[u] = {l, r};
int mid = l + r >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
pushup(u);
}
}
void modify(int u, int x, int y)
{
if(tr[u].l == x && tr[u].r == x)
{
tr[u].xsum = y;
return;
}
int mid = tr[u].l + tr[u].r >> 1;
if(x <= mid) modify(u << 1, x, y);
else modify(u << 1 | 1, x, y);
pushup(u);
}
int query(int u, int l, int r)
{
if(tr[u].l >= l && tr[u].r <= r) return tr[u].xsum;
int mid = tr[u].l + tr[u].r >> 1;
int res = 0;
if(l <= mid) res ^= query(u << 1, l, r);
if(r > mid) res ^= query(u << 1 | 1, l, r);
return res;
}
int query_tree(int u)
{
return query(1, id[u], id[u] + sz[u] - 1);
}
int main()
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++) scanf("%d", &w[i]);
memset(h, -1, sizeof h);
for(int i = 2; i <= n; i ++)
{
int a, b;
scanf("%d%d", &a, &b);
add(a, b), add(b, a);
}
dfs1(1, -1, 1);
dfs2(1, 1);
build(1, 1, cnt);
while(m --)
{
int op;
scanf("%d", &op);
if(op == 1)
{
int x, y;
scanf("%d%d", &x, &y);
modify(1, id[x], y);
}
else
{
int x;
scanf("%d", &x);
printf("%d\n", query_tree(x));
}
}
return 0;
}