#include <bits/stdc++.h>
using namespace std;
const int N=2e5;
int n,m,u,v,opt,x,k,y,ans;
int val[N+5];
struct Edge{
int cnt=1;
int head[N+5],to[(N<<1)+5],nxt[(N<<1)+5];
void addEdge(int u,int v){
to[cnt]=v,nxt[cnt]=head[u],head[u]=cnt++;
return ;
}
}edge;
struct Lca{
int faz[N+5],siz[N+5],top[N+5],dep[N+5],son[N+5];
void getSon(int u,int f){
siz[u]=1,son[u]=0;
for(int i=edge.head[u];i;i=edge.nxt[i]){
int v=edge.to[i];
if(v==f)continue;
dep[v]=dep[u]+1;
faz[v]=u;
getSon(v,u);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]])son[u]=v;
}
return ;
}
void getList(int u,int rt){
top[u]=rt;
if(son[u])getList(son[u],rt);
for(int i=edge.head[u];i;i=edge.nxt[i]){
int v=edge.to[i];
if(v==faz[u]||v==son[u])continue;
getList(v,v);
}
return ;
}
int lca(int u,int v){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]])swap(u,v);
u=faz[top[u]];
}
if(dep[u]<dep[v])swap(u,v);
return v;
}
int getDis(int x,int y){
return dep[x]+dep[y]-2*dep[lca(x,y)];
}
}lca;
struct SegTree{
int cnt;
int root[N+5],sum[(N<<5)+5],lc[(N<<5)+5],rc[(N<<5)+5];
void pushup(int u){
sum[u]=sum[lc[u]]+sum[rc[u]];
return ;
}
void change(int &u,int l,int r,int pos,int v){
if(!u)u=++cnt;
if(l==r){
sum[u]+=v;
return ;
}
int mid=(l+r)>>1;
if(pos<=mid)change(lc[u],l,mid,pos,v);
else change(rc[u],mid+1,r,pos,v);
pushup(u);
return ;
}
int query(int u,int l,int r,int x,int y){
if(!u||r<x||l>y)return 0;
if(x<=l&&r<=y)return sum[u];
int mid=(l+r)>>1;
return query(lc[u],l,mid,x,y)+query(rc[u],mid+1,r,x,y);
}
}sg,ch;
struct PointTree{
int root;
int siz[N+5],mxp[N+5],faz[N+5],dis[N+5][25],dep[N+5];
bool vis[N+5];
void getRoot(int u,int f,int tot){
siz[u]=1,mxp[u]=0;
for(int i=edge.head[u];i;i=edge.nxt[i]){
int v=edge.to[i];
if(v==f||vis[v])continue;
siz[u]=siz[v]+1;
mxp[u]=max(mxp[u],siz[v]);
}
mxp[u]=max(mxp[u],tot-siz[u]);
if(mxp[u]<mxp[root])root=u;
return ;
}
void buildSg(int u,int f,int rt,int d){
sg.change(sg.root[rt],0,n,d,val[u]);
for(int i=edge.head[u];i;i=edge.nxt[i]){
int v=edge.to[i];
if(v==f||vis[v])continue;
buildSg(v,u,rt,d+1);
}
return ;
}
void buildCh(int u,int f,int rt,int d){
ch.change(ch.root[rt],0,n,d,val[u]);
for(int i=edge.head[u];i;i=edge.nxt[i]){
int v=edge.to[i];
if(v==f||vis[v])continue;
buildCh(v,u,rt,d+1);
}
return ;
}
void build(int u){
vis[u]=true;
buildSg(u,0,u,0);
for(int i=edge.head[u];i;i=edge.nxt[i]){
int v=edge.to[i];
if(vis[v])continue;
root=0;
getRoot(v,0,siz[v]);
buildCh(v,0,root,1);
faz[root]=u,dep[root]=dep[u]+1;
build(root);
}
return ;
}
void init(){
mxp[0]=n;
getRoot(1,0,n);
build(root);
lca.getSon(1,0),lca.getList(1,1);
for(int i=1;i<=n;i++){
for(int j=i;j;j=faz[j])dis[i][dep[i]-dep[j]]=lca.getDis(i,j);
}
return ;
}
void change(int x,int y){
sg.change(sg.root[x],0,n,0,y-val[x]);
for(int i=x;faz[i];i=faz[i]){
int d=dis[x][dep[x]-dep[faz[i]]];
sg.change(sg.root[faz[i]],0,n,d,y-val[x]);
ch.change(ch.root[i],0,n,d,y-val[x]) ;
}
val[x]=y;
return ;
}
int query(int x,int y){
int res=sg.query(sg.root[x],0,n,0,y);
for(int i=x;faz[i];i=faz[i]){
int d=dis[x][dep[x]-dep[faz[i]]];
res+=sg.query(sg.root[faz[i]],0,n,0,y-d);
res-=ch.query(ch.root[i],0,n,0,y-d);
}
return res;
}
}pt;
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&val[i]);
for(int i=1;i<n;i++){
scanf("%d%d",&u,&v);
edge.addEdge(u,v),edge.addEdge(v,u);
}
pt.init();
for(int i=1;i<=m;i++){
scanf("%d",&opt);
if(opt==0){
scanf("%d%d",&x,&k);
x^=ans,k^=ans;
ans=pt.query(x,k);
printf("%d\n",ans);
}else{
scanf("%d%d",&x,&y);
x^=ans,y^=ans;
pt.change(x,y);
}
}
return 0;
}