#include<bits/stdc++.h>
#define efo(s,k,x) for(register int s=k.h[x];~s;s=k.ne[s])
#define afo(s,k,x) for(register int s=k;s>=x;--s)
#define fo(s,k,x) for(register int s=k;s<=x;++s)
using namespace std;
inline int max(int a,int b)
{
return a<b?b:a;
}
inline int min(int a,int b)
{
return a>b?b:a;
}
typedef pair<int,int> P;
const int N=500005,INF=0x3f3f3f3f;
int n,m,num[N];
int fa[N];
vector<int> E[N];
inline void dfs(int now)
{
for(auto v:E[now])
{
if(v==fa[now]) continue;
fa[v]=now;
}
}
int lazy[N];
struct DT
{
int root[N],ls[N*20],rs[N*20],siz[N*20],base[N*20],ans[N*20],cnt;
inline void push_up(int now)
{
siz[now]=ans[now]=0;
if(ls[now]) siz[now]+=siz[ls[now]],ans[now]^=ans[ls[now]];
if(rs[now])
{
siz[now]+=siz[rs[now]],ans[now]^=ans[rs[now]];
if(siz[rs[now]]&1) ans[now]|=(1<<(base[now]+1));
}
}
inline void add(int &now,int sum,int p)
{
if(!now) now=++cnt;
base[now]=p;
if(p>20)
{
++siz[now];
return ;
}
add(((sum&1)?rs[now]:ls[now]),sum>>1,p+1);
push_up(now);
}
inline void clear(int now,int sum)
{
if(base[now]>20)
{
--siz[now];
return ;
}
clear(((sum&1)?rs[now]:ls[now]),sum>>1);
push_up(now);
}
inline void exchange(int now)
{
swap(ls[now],rs[now]);
if(ls[now]) exchange(ls[now]);
push_up(now);
}
inline void change(int now,int p)
{
if(fa[now]) clear(root[fa[now]],num[now]+lazy[fa[now]]);
num[now]+=p;
if(fa[now]) add(root[fa[now]],num[now]+lazy[fa[now]],0);
}
}DT;
signed main()
{
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>n>>m;
fo(i,1,n-1)
{
int x,y;
cin>>x>>y;
E[x].push_back(y);
E[y].push_back(x);
}
fo(i,1,n) cin>>num[i];
dfs(1);
fo(i,2,n) DT.add(DT.root[fa[i]],num[i],0);
fo(i,1,m)
{
int opt,x,v;
cin>>opt>>x;
if(opt==2) cin>>v;
if(opt==1)
{
DT.exchange(DT.root[x]),++lazy[x];
DT.change(fa[x],1);
}
else if(opt==2) DT.change(x,-v);
else cout<<(DT.ans[x]^(fa[x]?(num[fa[x]]+lazy[fa[fa[x]]]):0))<<"\n";
}
return 0;
}