#include<cstdio>
#include<vector>
#include<algorithm>
#define ll long long
using namespace std;
int n,q,tot1,tot2,vistime;
int a[100005],dfn[100005],rdfn[100005],siz[100005],fa[100005][18],trie1[100005*33][2],val1[100005*33],rt1[100005];
int trie2[100005*33][2],val2[100005*33],rt2[100005],dep[100005];
vector<int> g[100005];
void dfs(int u,int f){
dfn[u]=++vistime;
dep[u]=dep[f]+1;
siz[u]=1;
rdfn[vistime]=u;
fa[u][0]=f;
for(auto v:g[u])if(v!=f){
dfs(v,u);
siz[u]+=siz[v];
}
}
void insert1(int u,int lst,int x){
for(int i=(1<<30);i;i>>=1){
val1[u]=val1[lst]+1;
int A=bool(x&i);
if(A==1){
trie1[u][0]=trie1[lst][0];
if(!trie1[u][1]) trie1[u][1]=++tot1;
u=trie1[u][1];
lst=trie1[lst][1];
}
else{
trie1[u][1]=trie1[lst][1];
if(!trie1[u][0]) trie1[u][0]=++tot1;
u=trie1[u][0];
lst=trie1[lst][0];
}
}
val1[u]=val1[lst]+1;
}
int query1(int l,int r,int x){
int ret=0;
for(int i=(1<<30);i;i>>=1){
int A=bool(x&i);
if(val1[trie1[r][A^1]]-val1[trie1[l][A^1]]){
l=trie1[l][A^1];
r=trie1[r][A^1];
ret+=i;
}
else{
l=trie1[l][A];
r=trie1[r][A];
}
}
return ret;
}
void insert2(int u,int lst,int x){
for(int i=(1<<30);i;i>>=1){
val2[u]=val2[lst]+1;
int A=bool(x&i);
if(A==1){
trie2[u][0]=trie2[lst][0];
if(!trie2[u][1]) trie2[u][1]=++tot2;
u=trie2[u][1];
lst=trie2[lst][1];
}
else{
trie2[u][1]=trie2[lst][1];
if(!trie2[u][0]) trie2[u][0]=++tot2;
u=trie2[u][0];
lst=trie2[lst][0];
}
}
val2[u]=val2[lst]+1;
}
int query2(int l,int r,int x){
int ret=0;
for(int i=(1<<30);i;i>>=1){
int A=bool(x&i);
if(val2[trie2[r][A^1]]-val2[trie2[l][A^1]]){
l=trie2[l][A^1];
r=trie2[r][A^1];
ret+=i;
}
else{
l=trie2[l][A];
r=trie2[r][A];
}
}
return ret;
}
int lca(int u,int v){
if(dep[u]<dep[v]) swap(u,v);
for(int i=17;i>=0;i--){
if(dep[fa[u][i]]>=v){
u=fa[u][i];
}
}
if(u==v) return u;
for(int i=17;i>=0;i--){
if(fa[u][i]!=fa[v][i]){
u=fa[u][i];
v=fa[v][i];
}
}
return fa[u][0];
}
int main(){
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
dfs(1,0);
for(int i=1;i<=n;i++){
rt1[i]=++tot1;
insert1(rt1[i],rt1[i-1],a[rdfn[i]]);
rt2[i]=++tot2;
insert2(rt2[i],rt2[fa[i][0]],a[i]);
}
for(int k=1;k<=17;k++){
for(int i=1;i<=n;i++){
fa[i][k]=fa[fa[i][k-1]][k-1];
}
}
while(q--){
int op,u,v,x;
scanf("%d",&op);
if(op==1){
scanf("%d%d",&u,&x);
printf("%d\n",query1(rt1[dfn[u]-1],rt1[dfn[u]+siz[u]-1],x));
}
else{
scanf("%d%d%d",&u,&v,&x);
int LCA=lca(u,v);
printf("%d\n",max(query2(rt2[fa[LCA][0]],rt2[u],x),query2(rt2[fa[LCA][0]],rt2[v],x)));
}
}
return 0;
}