#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(register int i=a,i##end=b;i<=i##end;i++)
#define drep(i,a,b) for(register int i=a,i##end=b;i>=i##end;i--)
#define erep(i,x) for(int i=head[x];i;i=nxt[i])
inline int read(){
int x=0,f=1;char c=getchar();
while(c<48||c>57){if(c=='-')f=-1;c=getchar();}
while(c>=48&&c<=57)x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
using namespace std;
const int M=100005,inf=1e9;
int n,m,tot,etot;
int A[M],pos[M],L[M],R[M],top[M],size[M],son[M],fa[M];
int g[M][2],f[M][2];
int head[M],E[M<<1],nxt[M<<1];
inline void add(int u,int v){
E[++etot]=v,nxt[etot]=head[u];
head[u]=etot;
}
struct martix {
int A[2][2];
void set(int pos){
A[0][0]=g[pos][0],A[0][1]=g[pos][1];
A[1][0]=g[pos][0],A[1][1]=-inf;
}
void reset() {
rep(i,0,1)rep(j,0,1)A[i][j]=-inf;
}
martix operator *(const martix &a)const {
martix ans;ans.reset();
rep(i,0,1)rep(j,0,1)rep(k,0,1)ans.A[i][k]=max(ans.A[i][k],A[i][j]+a.A[j][k]);
return ans;
}
};
struct seg {
martix t[M<<2];
#define ls p<<1
#define rs p<<1|1
void build(int p,int l,int r){
if(l==r){t[p].set(pos[l]);return ;}
int mid=l+r>>1;
build(ls,l,mid),build(rs,mid+1,r);
t[p]=t[ls]*t[rs];
}
void update(int p,int l,int r,int x){
if(l==r){t[p].set(pos[l]);return ;}
int mid=l+r>>1;
if(x<=mid)update(ls,l,mid,x);
else update(rs,mid+1,r,x);
t[p]=t[ls]*t[rs];
}
martix query(int p,int pl,int pr,int l,int r){
if(pl==l&&pr==r)return t[p];
int mid=pl+pr>>1;
if(r<=mid)return query(ls,pl,mid,l,r);
else if(l>mid)return query(rs,mid+1,pr,l,r);
else return query(ls,pl,mid,l,mid)*query(rs,mid+1,pr,mid+1,r);
}
}T;
void upd(int x,int w){
f[x][1]+=w-A[x],g[x][1]+=w-A[x];
A[x]=w;
while(x){
// printf("x=%d,top=%d\n",x,top[x]);
martix old=T.query(1,1,n,L[top[x]],R[top[x]]);
T.update(1,1,n,L[x]);
martix now=T.query(1,1,n,L[top[x]],R[top[x]]);
int up=fa[top[x]];
g[up][0]-=max(old.A[0][0],old.A[0][1]);
g[up][0]+=max(now.A[0][0],now.A[0][1]);
g[up][1]-=old.A[0][0];
g[up][1]+=now.A[0][0];
x=up;
}
}
void dfs1(int x,int fat){
fa[x]=fat,size[x]=1;
erep(i,x){
int to=E[i];
if(to==fat)continue;
dfs1(to,x);
size[x]+=size[to];
if(size[to]>size[son[x]])son[x]=to;
}
}
void dfs2(int x,int tp){
g[x][0]=0,g[x][1]=A[x];
top[x]=tp;
pos[L[x]=++tot]=x;
if(son[x]){
dfs2(son[x],tp);
R[x]=R[son[x]];
}else R[x]=tot;
erep(i,x){
int to=E[i];
if(to==fa[x]||to==son[x])continue;
dfs2(to,to);
g[x][0]+=max(f[to][0],f[to][1]);
g[x][1]+=f[to][0];
}
if(son[x]){
f[x][0]=g[x][0]+max(f[son[x]][0],f[son[x]][1]);
f[x][1]=g[x][1]+f[son[x]][0];
}else f[x][0]=g[x][0],f[x][1]=g[x][1];
}
int main() {
// freopen("test.in","r",stdin);
// freopen("data.out","w",stdout);
n=read(),m=read();
rep(i,1,n)A[i]=read();
rep(i,1,n-1){
int u=read(),v=read();
add(u,v),add(v,u);
}
dfs1(1,0),dfs2(1,1);
T.build(1,1,n);
rep(i,1,m){
int x=read(),w=read();
upd(x,w);
martix res=T.query(1,1,n,L[1],R[1]);
printf("%d\n",max(res.A[0][0],res.A[0][1]));
}
return 0;
}
/*
f[i][0/1] i的子树,i 不选/选的最大值
g[i][0/1] i的子树除去重儿子
f[i][0]=g[i][0]+max(f[son][0],f[son][1])
f[i][1]=g[i][1]+f[son][0]
g[i][0]=∑max f[to][0/1]
g[i][1]=∑f[to][0]
构造一个2*2矩阵
使得 [f(son,0),f(son,1)]->[f(i,0),f(i,1)]
g[i][0] g[i][1]
g[i][0] -inf
用树剖更新,一段链可以用矩乘算出top的f矩阵,再更新f[top]的g矩阵。
*/