#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cctype>
#include <vector>
#define _for(i,a,b) for(int i=(a);i<(b);++i)
#define _rep(i,a,b) for(int i=(a);i<=(b);++i)
using namespace std;
typedef long long LL;
inline int read_int(){
int t=0;bool sign=false;char c=getchar();
while(!isdigit(c)){sign|=c=='-';c=getchar();}
while(isdigit(c)){t=(t<<1)+(t<<3)+(c&15);c=getchar();}
return sign?-t:t;
}
inline void write(LL x){
register char c[21],len=0;
if(!x)return putchar('0'),void();
if(x<0)x=-x,putchar('-');
while(x)c[++len]=x%10,x/=10;
while(len)putchar(c[len--]+48);
}
inline void enter(LL x){write(x),putchar('\n');}
const int MAXN=1e5+5,MAXM=20,inf=1e6+5;
struct Edge{
int to,next;
}edge[MAXN<<1];
int n,q,edge_cnt,head[MAXN];
inline void Insert(int u,int v){
edge[++edge_cnt].to=v;
edge[edge_cnt].next=head[u];
head[u]=edge_cnt;
}
int a[MAXN],sz[MAXN],dep[MAXN],mson[MAXN],f[MAXN],tot_sz,root,root_sz;
bool vis[MAXN];
struct LCA{
int B[MAXN<<1],F[MAXN<<1],pos[MAXN],n;
int d[MAXN<<1][MAXM],lg2[MAXN<<1];
inline void push(int index,int depth){
F[n]=index;
B[n]=depth;
n++;
}
void dfs(int u,int fa,int depth){
pos[u]=n;dep[u]=depth;
push(u,depth);
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(v==fa)
continue;
dfs(v,u,depth+1);
push(u,depth);
}
}
void build(int root){
dfs(root,-1,0);
lg2[1]=0;
_rep(i,2,n)
lg2[i]=lg2[i>>1]+1;
_for(i,0,n)
d[i][0]=i;
for(int j=1;(1<<j)<=n;j++){
_for(i,0,n+1-(1<<j)){
if(B[d[i][j-1]]<B[d[i+(1<<(j-1))][j-1]])
d[i][j]=d[i][j-1];
else
d[i][j]=d[i+(1<<(j-1))][j-1];
}
}
}
int query(int a,int b){
int lef=pos[a],rig=pos[b],len=abs(rig-lef)+1;
if(lef>rig)
swap(lef,rig);
if(B[d[lef][lg2[len]]]<B[d[rig-(1<<lg2[len])+1][lg2[len]]])
return F[d[lef][lg2[len]]];
else
return F[d[rig-(1<<lg2[len])+1][lg2[len]]];
}
}lca;
int get_dis(int a,int b){
return dep[a]+dep[b]-(dep[lca.query(a,b)]<<1);
}
#define lowbit(x) x&(-x)
struct BIT{
int n;
vector<int>c;
void build(int n){
this->n=n;
c.resize(n+1);
}
void add(int pos,int v){
++pos;
while(pos<=n){
c[pos]+=v;
pos+=lowbit(pos);
}
}
int query(int pos){
pos=min(pos+1,n);
int ans=0;
while(pos){
ans+=c[pos];
pos-=lowbit(pos);
}
return ans;
}
}tree_1[MAXN],tree_2[MAXN];
void find_root(int u,int fa){
sz[u]=1;mson[u]=0;
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(vis[v]||v==fa)
continue;
find_root(v,u);
sz[u]+=sz[v];
mson[u]=max(mson[u],sz[v]);
}
mson[u]=max(mson[u],tot_sz-sz[u]);
if(mson[u]<root_sz){
root=u;
root_sz=mson[u];
}
}
void build_tree(int u,int fa){
int cur_sz=tot_sz;
vis[u]=true;f[u]=fa;
tree_1[u].build((cur_sz>>1)+1);tree_2[u].build(cur_sz+1);
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(vis[v])
continue;
tot_sz=sz[v]>sz[u]?cur_sz-sz[u]:sz[v];root_sz=MAXN;
find_root(v,u);
build_tree(root,u);
}
}
void update(int u,int val){
tree_1[u].add(0,val);
for(int i=u;f[i];i=f[i]){
int d=get_dis(u,f[i]);
tree_1[f[i]].add(d,val);
tree_2[i].add(d,val);
}
}
int query(int u,int k){
int ans=tree_1[u].query(k);
for(int i=u;f[i];i=f[i]){
int d=get_dis(u,f[i]);
if(d>k)
continue;
ans+=tree_1[f[i]].query(k-d);
ans-=tree_2[i].query(k-d);
}
return ans;
}
int main()
{
n=read_int(),q=read_int();
_rep(i,1,n)
a[i]=read_int();
int u,v;
_for(i,1,n){
u=read_int(),v=read_int();
Insert(u,v);
Insert(v,u);
}
lca.build(1);
root_sz=MAXN;
tot_sz=n;
find_root(1,0);
build_tree(root,0);
_rep(i,1,n)
update(i,a[i]);
int last=0,opt,x,y;
while(q--){
opt=read_int(),x=read_int()^last,y=read_int()^last;
if(opt==0)
enter(last=query(x,y));
else{
update(x,y-a[x]);
a[x]=y;
}
}
return 0;
}