RT
#include<bits/stdc++.h>
using namespace std;
const int maxn=2000010;
inline int read()
{
int x=0;int f=1;char c;
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
return ~f?x:-x;
}
struct node{int to,nxt;}edge[maxn];
int head[maxn],tot_edge;int n,m;int a[maxn];
void add(int x,int y)
{
edge[++tot_edge].to=y;
edge[tot_edge].nxt=head[x];
head[x]=tot_edge;
}
struct BIT
{
int siz;
vector<int> bit;
int lowbit(int x){return x&-x;}
void build(int sz){for(int i=0;i<=sz+3;i++) bit.push_back(0);siz=sz+1;}
void update(int x,int v){x++;for(;x<=siz;x+=lowbit(x)) bit[x]+=v;}
int query(int x)
{
x++;x=min(x,siz);
int res=0;
for(;x;x-=lowbit(x)) res+=bit[x];
return res;
}
}T1[maxn],T2[maxn];
namespace dfs_to_lca
{
int dfn[maxn],dfn_cnt=0;int dep[maxn];
int anc[maxn][21];
int get(int x,int y){return dfn[x]<dfn[y]?x:y;}
void dfs(int u,int fa)
{
anc[dfn[u]=++dfn_cnt][0]=fa;dep[u]=dep[fa]+1;
for(int i=head[u];i;i=edge[i].nxt)
{
int v=edge[i].to;
if(v==fa) continue;
dfs(v,u);
}
}
void pre_st()
{
for(int i=1;i<=__lg(n);i++)
for(int j=1;j+(1<<i)-1<=n;j++)
anc[j][i]=get(anc[j][i-1],anc[j+(1<<(i-1))][i-1]);
}
int lca(int x,int y)
{
if(x==y) return x;
if((x=dfn[x])>(y=dfn[y]))x^=y^=x^=y;
int d=__lg(y-x++);
return get(anc[x][d],anc[y-(1<<d)+1][d]);
}
int dis(int x,int y){return dep[x]+dep[y]-2*dep[lca(x,y)];}
}
namespace divide_and_conquer_tree
{
int vis[maxn],siz[maxn],fa_siz[maxn],fa_on_tree[maxn];
int rt,heavy;
void dfs1(int u,int fa)
{
siz[u]=1;
for(int i=head[u];i;i=edge[i].nxt)
{
int v=edge[i].to;
if(v==fa||vis[v]) continue;
dfs1(v,u);
siz[u]+=siz[v];
}
}
void dfs2(int u,int fa)
{
fa_siz[u]=siz[rt]-siz[u];
for(int i=head[u];i;i=edge[i].nxt)
{
int v=edge[i].to;
if(v==fa||vis[v]) continue;
fa_siz[u]=max(fa_siz[u],siz[v]);
dfs2(v,u);
}
if(fa_siz[heavy]>fa_siz[u]) heavy=u;
}
void solve(int u,int fa)
{
rt=heavy=u;
dfs1(u,u);dfs2(u,u);
T1[heavy].build(siz[heavy]);
T2[heavy].build(siz[heavy]);
fa_on_tree[heavy]=fa;
vis[heavy]=1;int tmp=heavy;
for(int i=head[tmp];i;i=edge[i].nxt){int v=edge[i].to;if(!vis[v]) solve(v,tmp);}
}
void change(int u,int k)
{
for(int i=u;i;i=fa_on_tree[i]) T1[i].update(dfs_to_lca::dis(u,i),k);
for(int i=u;fa_on_tree[i];i=fa_on_tree[i]) T2[i].update(dfs_to_lca::dis(u,fa_on_tree[i]),k);
}
int query(int x,int k)
{
int ans=0;
ans+=T1[x].query(k);
for(int i=x;fa_on_tree[i];i=fa_on_tree[i])
{
int dis=dfs_to_lca::dis(x,fa_on_tree[i]);
if(k>=dis) ans+=T1[fa_on_tree[i]].query(k-dis)-T2[i].query(k-dis);
}
return ans;
}
}
int main()
{
freopen("P6329_1.in","r",stdin);
//freopen("P6329_user.out","w",stdout);
n=read();m=read();
time_t st,ed;st=clock();
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1,x,y;i<n;i++){x=read();y=read();add(x,y);add(y,x);}
divide_and_conquer_tree::solve(1,0);
dfs_to_lca::dfs(1,0);dfs_to_lca::pre_st();
/*for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) cout<<i<<' '<<j<<' '<<dfs_to_lca::dis(i,j)<<endl;*/
for(int i=1;i<=n;i++) divide_and_conquer_tree::change(i,a[i]);
int last_ans=0;
for(int i=1;i<=m;i++)
{
int opt,x,y;
opt=read();x=read();y=read();
x^=last_ans;y^=last_ans;
if(opt==0) {last_ans=divide_and_conquer_tree::query(x,y);cout<<last_ans<<endl;}
else {divide_and_conquer_tree::change(x,y-a[x]);a[x]=y;}
}
ed=clock();
cerr<<endl<<double(ed-st)<<"ms"<<endl;
return 0;
}