#include <cstdio>
#define re register
#define get getchar()
inline int read(){
re int x = 0 , f = 1;re char c = get;
while (c < '0' || c > '9') f ^= !(c ^ 45) , c = get;
while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48) , c = get;
return f ? x : -x;
}
const int MAXN = 2e5 + 1;
int n = read() , q = read();
struct edge{
int nxt , to;
}a[MAXN];
int head[MAXN] , w[MAXN] , wt[MAXN] , tot , cnt;
int id[MAXN] , top[MAXN] , fa[MAXN];
int son[MAXN] , siz[MAXN] , tree[MAXN << 2] , dep[MAXN];
inline void swap(re int &x , re int &y){x ^= y ^= x ^= y;}
inline void add(re int u , re int v){
a[++ tot].nxt = head[u];
a[head[u] = tot].to = v;
}
inline void dfs1(re int now , re int fath){
dep[now] = dep[fath] + 1;fa[now] = fath;siz[now] = 1;
for (re int i = head[now]; i ;i = a[i].nxt){
re int y = a[i].to;
if (y == fath) continue;
dfs1(y , now);
siz[now] += siz[y];
if (siz[y] > siz[son[now]]) son[now] = y;
}
}
inline void dfs2(re int now , re int topf){
top[now] = topf;id[now] = ++ cnt;wt[cnt] = w[now];
if (son[now]) dfs2(son[now] , topf);
for (re int i = head[now]; i ;i = a[i].nxt){
re int y = a[i].to;
if (y == fa[now] || y == son[now]) continue;
dfs2(y , y);
}
}
inline int ls(re int p){return p << 1;}
inline int rs(re int p){return p << 1 | 1;}
inline void push_up(re int p){tree[p] = tree[ls(p)] ^ tree[rs(p)];}
inline void build(re int p , re int l , re int r){
if (l == r) return (void)(tree[p] = wt[l]);
re int mid = l + r >> 1;
build(ls(p) , l , mid);
build(rs(p) , mid + 1 , r);
push_up(p);
}
inline void update(re int p , re int l , re int r , re int q , re int k){
if (l == r) return (void)(tree[p] = k);
re int mid = l + r >> 1;
if (q <= mid) update(ls(p) , l , mid , q , k);
else update(rs(p) , mid + 1 , r , q , k);
push_up(p);
}
inline int query(re int p , re int l , re int r , re int nl , re int nr){
if (nl <= l && r <= nr) return tree[p];
re int mid = l + r >> 1 , res = 0;
if (nl <= mid) res ^= query(ls(p) , l , mid , nl , nr);
if (nr > mid) res ^= query(rs(p) , mid + 1 , r , nl , nr);
return res;
}
inline int query_chain(re int u , re int v){
re int res = 0;
while (top[u] ^ top[v]){
if (dep[top[u]] < dep[top[v]]) swap(u , v);
res ^= query(1 , 1 , n , id[top[u]] , id[u]);
u = fa[top[u]];
}
if (dep[u] > dep[v]) swap(u , v);
return res ^= query(1 , 1 , n , id[u] , id[v]);
}
signed main(){
for (re int i = 1;i <= n;++ i) w[i] = read();
for (re int i = 1;i < n;++ i){
re int u = read() , v = read();
add(u , v) , add(v , u);
}
dfs1(1 , 0);dfs2(1 , 1);build(1 , 1 , n);
while (q --){
re int opt = read() , x = read() , y = read();
switch (opt){
case 1:update(1 , 1 , n , id[x] , y);break;
case 2:printf("%d\n" , query_chain(x , y));break;
}
}
return 0;
}