细节详见代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define Debug(x) cout<<#x<<"="<<x<<endl
#define int long long
using namespace std;
typedef long long LL;
const LL INF=1e16+7;
inline LL read(){
register LL x=0,f=1;register char c=getchar();
while(c<48||c>57){if(c=='-')f=-1;c=getchar();}
while(c>=48&&c<=57)x=(x<<3)+(x<<1)+(c&15),c=getchar();
return f*x;
}
const int N=1e5+5;
const int M=2e5+5;
struct Edge{
int v,nxt;
}e[M];
int first[N],Ecnt=0;
inline void Add_edge(int u,int v){
e[++Ecnt]=(Edge){v,first[u]};
first[u]=Ecnt;
}
int a[N];LL dp[N][2];
struct Matrix{
LL a[2][2];
Matrix (){a[0][0]=a[0][1]=a[1][0]=a[1][1]=INF;}//初始化
inline LL* operator [](int x){return a[x];}
inline friend Matrix operator * (Matrix a,Matrix b){
Matrix res;
for(int i=0;i<2;i++){
for(int j=0;j<2;j++)
for(int k=0;k<2;k++)
res[i][j]=min(res[i][j],a[i][k]+b[k][j]);
}
return res;
}
}g[N],f[N];
namespace LCT{
int par[N],ch[N][2];
#define ls (ch[x][0])
#define rs (ch[x][1])
inline bool chk(int x){
return ch[par[x]][1]==x;
}
inline bool nrt(int x){
return ch[par[x]][0]==x||ch[par[x]][1]==x;
}
inline void pushup(int x){
f[x]=g[x];//虚儿子由于是轻边,一定是要f[rs]*g[x]*f[ls],从下往上更新也符合dp思路
if(rs) f[x]=f[rs]*f[x];
if(ls) f[x]=f[x]*f[ls];
}
inline void rotate(int x){
int y=par[x],z=par[y],k=chk(x),w=ch[x][k^1];
ch[y][k]=w,par[w]=y;
if(nrt(y)) ch[z][chk(y)]=x; par[x]=z;
ch[x][k^1]=y,par[y]=x;
pushup(y);pushup(x);
}
inline void splay(int x){
while(nrt(x)){
int y=par[x];
if(nrt(y)){
if(chk(x)==chk(y)) rotate(y);
else rotate(x);
}
rotate(x);
}
}
inline void access(int x){
for(int y=0;x;x=par[y=x]){
splay(x);
if(rs){
g[x][0][1]+=min(f[rs][1][0],f[rs][1][1]);//rs变为虚边
g[x][1][1]+=min(f[rs][1][0],f[rs][1][1]);
g[x][1][0]+=f[rs][1][1];
}
if(y){
g[x][0][1]-=min(f[y][1][0],f[y][1][1]);//y变为实边
g[x][1][1]-=min(f[y][1][0],f[y][1][1]);
g[x][1][0]-=f[y][1][1];
}
rs=y;
pushup(x);
}
}
inline void modify(int x,int val){
access(x);splay(x);
g[x][0][1]+=val-a[x];
g[x][1][1]+=val-a[x];
pushup(x);
a[x]=val;// x[a]==a[x]
}
#undef ls
#undef rs
}using namespace LCT;
inline void dfs(int u,int pre){
dp[u][1]=a[u];
par[u]=pre;
for(int i=first[u];i;i=e[i].nxt){
int v=e[i].v;
if(v==pre) continue;
dfs(v,u);
dp[u][1]+=min(dp[v][0],dp[v][1]);
dp[u][0]+=dp[v][1];
}
f[u][0][1]=f[u][1][1]=dp[u][1];
f[u][1][0]=dp[u][0];
g[u]=f[u];//一开始全是虚子树
}
signed main(){
int n=read(),m=read();char op[10];scanf("%s",op);
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<=n-1;i++){
int x=read(),y=read();
Add_edge(x,y);
Add_edge(y,x);
}
dfs(1,0);
for(int i=1;i<=m;i++){
int aa=read(),x=read(),bb=read(),y=read();
int va=a[aa],vb=a[bb];
if(x) modify(aa,0);//强制选:赋为0才能保证能选到
else modify(aa,va+INF);
if(y) modify(bb,0);
else modify(bb,vb+INF);
splay(1);
LL ans=min(f[1][1][0],f[1][1][1]);
if(ans>=INF) puts("-1");
else{
if(x) ans+=va;//然后又加上这个点的答案
if(y) ans+=vb;
printf("%lld\n",ans);
}
modify(aa,va);modify(bb,vb);//又改回去
}
}