#include<bits/stdc++.h>
#define ls ((x)<<1)
#define rs ((x)<<1|1)
#define mid (l+r>>1)
using namespace std;
const int N=100005;
int read(){
int x=0,f=1;
char c=getchar();
while(!isdigit(c)) {
if(c=='-')
f=-1;
c=getchar();
}
while(isdigit(c))
x=x*10+c-'0',c=getchar();
return x*f;
}
vector<int> zaa[N];
int n,q;
int siz[N],fa[N],dep[N],endson[N],son[N],id[N],top[N],a[N],sum[N];
void dfs1(int now,int father){
siz[now]=1;
fa[now]=father;
dep[now]=dep[father]+1;
for(auto &v:zaa[now]){
if(v==father) continue;
dfs1(v,now);
siz[now]+=siz[v];
if(siz[v]>siz[son[now]]){
son[now]=v;
}
}
}
int cnt=0;
void dfs2(int now,int tp){
id[now]=++cnt;
top[now]=tp;
sum[id[now]]=sum[id[fa[now]]]^a[now];
if(!son[now])
return;
dfs2(son[now],tp);
for(auto &v:zaa[now]){
if(v==fa[now]||v==son[now])
continue;
dfs2(v,v);
}
endson[now]=cnt;
}
int LCA(int x,int y) {
while(top[x]!=top[y]) {
if(dep[top[x]]<dep[top[y]])
swap(x,y);
x=fa[top[x]];
}
return dep[x]<dep[y]?x:y;
}
//---------------------------------------------树剖
int tree[N<<2];
void build(int x,int l,int r) {
if(l==r) {
tree[x]=sum[l];
return ;
}
build(ls,l,mid);
build(rs,mid+1,r);
}
void modify(int x,int l,int r,int L,int R,int v) {
if(l==L&&r==R) {
tree[x]^=v;
return ;
}
if(R<=mid)
modify(ls,l,mid,L,R,v);
if(L>mid)
modify(rs,mid+1,r,L,R,v);
}
int query(int x,int l,int r,int p) {
if(l==r) {
return tree[x];
}
if(p<=mid)
return tree[x]^query(ls,l,mid,p);
else
return tree[x]^query(rs,mid+1,r,p);
}
//-------------------------------------线段树
int main() {
n=read(),q=read();
for(int i=1;i<=n;i++)
a[i]=read();
for(int i=1;i<n;i++) {
int x,y;
x=read(),y=read();
zaa[x].push_back(y);
zaa[y].push_back(x);
}
dfs1(1,0);
dfs2(1,1);
build(1,1,n);
while(q--) {
int op,x,y;
op=read(),x=read(),y=read();
if(op==1){
modify(1,1,n,id[x],endson[x],(y^a[x]));
a[x]=y;
}
else{
int z=LCA(x,y);
int ans=(query(1,1,n,id[x])^query(1,1,n,id[y])^a[z]);
cout<<ans<<endl;
}
}
return 0;
}