/*震波*/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
const int maxn = 2e5 + 10;
int n,m;
inline int gc() {
static char buf[1000000], *p1 = buf, *p2 = buf;
return (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2)) ? EOF : *p1++;
//return getchar();
}
inline int read(){
char ch = gc();
int x = 0;
while(ch < '0' || ch > '9') ch = gc();
while(ch >= '0' && ch <= '9') x = x * 10 + ch - 48,ch = gc();
return x;
}
inline void write(int x){
if(!x) return;
write(x/10);
putchar(x%10+'0');
}
struct Edge{
int next,point;
}edge[maxn*2];
int head[maxn];
int dsiz[maxn];
int tot = 0;
inline void add(int x,int y){
edge[++tot].next = head[x];
edge[tot].point = y;
head[x] = tot;
}
int maxp[maxn];
int siz[maxn];
int vis[maxn];
int f[maxn];
int in[maxn];
int a[maxn];
int rt = 0;
int dep[maxn];
void getrt(int x,int fa,int sum){
siz[x] = 1; maxp[x] = 0;
for(register int i = head[x]; i ; i = edge[i].next){
int y = edge[i].point;
if(y == fa || vis[y]) continue;
getrt(y,x,sum);
siz[x] += siz[y];
maxp[x] = max(maxp[x],siz[y]);
}
maxp[x] = max(maxp[x],sum - siz[x]);
if(maxp[rt] > maxp[x]) rt = x;
}
#define T 20
inline int Min(int x,int y){
if(dep[x] < dep[y]) return x;
return y;
}
int g[maxn*2][21],intot;
void Dfs(int x,int fa){
g[++intot][0] = x;
in[x] = intot;
for(register int i = head[x]; i ; i = edge[i].next){
int y = edge[i].point;
if(y == fa) continue;
dep[y] = dep[x] + 1;
Dfs(y,x);
g[++intot][0] = x;
}
}
int lg2[maxn];
void rmq(){
lg2[1] = 0;
for(int i = 2; i <= intot; ++i) lg2[i] = lg2[i >> 1] + 1;
int t = lg2[intot];
for(register int j = 1; j <= t; ++j)
for(register int i = 1; i <= intot - (1 << j) + 1; ++i)
g[i][j] = Min(g[i][j-1],g[i+(1<<(j-1))][j-1]);
}
inline int lca(int l,int r){
l = in[l],r = in[r];
if(l > r) swap(l,r);
int t = lg2[r-l+1];
return Min(g[l][t],g[r-(1<<t)+1][t]);
}
inline int Dis(int x,int y){
return dep[x] + dep[y] - 2 * dep[lca(x,y)];
}
void build(int u,int sum){
vis[u] = 1; dsiz[u] = sum;
for(register int i = head[u]; i ; i = edge[i].next){
int v = edge[i].point;
if(vis[v]) continue;
int nowsum = (siz[v] > siz[u]) ? sum - siz[u] : siz[v];
maxp[rt = 0] = 1e9;
getrt(v,0,nowsum);
f[rt] = u;
build(rt,nowsum);
}
}
struct SegmentTree{
int lc[maxn*32],rc[maxn*32],dat[maxn*32];
int root[maxn];
int cnt;
void Insert(int &p,int l,int r,int pos,int v){
if(!p) p = ++cnt;
dat[p] += v;
if(l == r) return;
int mid = (l + r) >> 1;
if(pos <= mid) Insert(lc[p],l,mid,pos,v);
else Insert(rc[p],mid+1,r,pos,v);
}
int ask(int p,int l,int r,int a,int b){
if(a > b) return 0;
if(a <= l && b >= r) return dat[p];
int mid = (l + r) >> 1;
int ans = 0;
if(a <= mid)
ans += ask(lc[p],l,mid,a,b);
if(b > mid)
ans += ask(rc[p],mid+1,r,a,b);
return ans;
}
}t1,t2;
inline void Modify(int x,int v){
int idx = x;
while(x){
t1.Insert(t1.root[x],0,dsiz[x],Dis(idx,x),v);
if(f[x]) t2.Insert(t2.root[x],0,dsiz[x],Dis(idx,f[x]),v);
x = f[x];
}
}
inline int query(int x,int k){
int idx = x;
int lst = 0;
int ans = 0;
while(x){
int d = Dis(x,idx);
if(k - d < 0){
lst = x;
x = f[x];
continue;
}
ans += t1.ask(t1.root[x],0,dsiz[x],0,k-d);
if(lst) ans -= t2.ask(t2.root[lst],0,dsiz[lst],0,k-d);
lst = x;
x = f[x];
}
return ans;
}
void pre(){
build(rt,n);
for(register int i = 1; i <= n; ++i) Modify(i,a[i]);
}
int main()
{
n = read(),m = read();
for(int i = 1; i <= n; ++i)
a[i] = read();
for(int i = 1; i < n; ++i){
int x = read(),y = read();
add(x,y); add(y,x);
}
maxp[rt = 0] = 1e9;
getrt(1,0,n) ;
dep[rt] = 1;
Dfs(rt,0);
rmq();
pre();
int ans = 0;
for(int i = 1; i <= m; ++i){
int op = read();
if(op){
int x = read(),v = read();
x ^= ans,v ^= ans;
Modify(x,v-a[x]);
a[x] = v;
}
else{
int x = read(),k = read();
x ^= ans,k ^= ans;
ans = query(x,k);
if(!ans) putchar('0');
else
write(ans);
putchar('\n');
}
}
return 0;
}