• 思路:
    DDP板题,就常规思路:\(f[i][0/1]\)表示(不)选i点,的最小代价。\(g[i][0/1]\)即对应的f除去son[v]的贡献
    然后利用\(g->f\)的转移退出矩阵转移式,利用结合率线段树维护即可。
  • code:
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
typedef long long ll;
int fa[N],n,m,rt,mod,nxt[N],to[N],head[N],ecnt;
ll b[N],f[N][2],g[N][2],inf=1e17,a[N];
void add_edge(int u,int v) {nxt[++ecnt]=head[u];to[ecnt]=v;head[u]=ecnt;}
struct matr {
	ll z1,z2,z3,z4;
	matr friend operator*(matr u,matr v) {
		matr w;
		w.z1=min(u.z1+v.z1,u.z2+v.z3),w.z2=min(u.z1+v.z2,u.z2+v.z4);
		w.z3=min(u.z3+v.z1,u.z4+v.z3),w.z4=min(u.z3+v.z2,u.z4+v.z4);
		return w;
	}
};
struct seg {int l,r;matr w;}T[N];
void P_up(int x){T[x].w=T[x<<1].w*T[x<<1|1].w;}
void _Give(matr &tmp,int p) {tmp.z3=tmp.z4=g[p][1],tmp.z2=g[p][0];}
void Build(int x,int l,int r) {
	T[x].l=l,T[x].r=r;
	if(l==r) {_Give(T[x].w,b[l]);T[x].w.z1=inf;return;}
	int mid=(l+r)>>1;
	Build(x<<1,l,mid),Build(x<<1|1,mid+1,r);
	P_up(x);
}
void Update(int x,int p,int y) {
	if(T[x].l==T[x].r) {_Give(T[x].w,y);return;}
	int mid=(T[x].l+T[x].r)>>1;
	if(p<=mid) Update(x<<1,p,y);
	else Update(x<<1|1,p,y);
	P_up(x);
}
matr Query(int x,int l,int r) {
	if(l<=T[x].l&&T[x].r<=r) {return T[x].w;}
	int mid=(T[x].l+T[x].r)>>1;
	matr val;bool f1=0;
	if(l<=mid) val=Query(x<<1,l,r),f1=1;
	if(r>mid) {
		if(f1)val=val*Query(x<<1|1,l,r);
		else val=Query(x<<1|1,l,r);
	}
	return val;
}
int sz[N],son[N],top[N],ed[N],dfn[N],Time,dep[N];
void gt_son(int x) {
	sz[x]=1;
	for(int i=head[x];i;i=nxt[i]) {
		int y=to[i];if(y==fa[x])continue;
		dep[y]=dep[x]+1;fa[y]=x;
		gt_son(y);sz[x]+=sz[y];
		if(sz[son[x]]<sz[y])son[x]=y;
	}
}
void gt_top(int x,int Tp) {
	top[x]=Tp;ed[Tp]=x;dfn[x]=++Time;b[Time]=x;
	if(son[x])gt_top(son[x],Tp);
	for(int i=head[x];i;i=nxt[i]) {
		int y=to[i];
		if(y==fa[x]||y==son[x])continue;
		gt_top(y,y);
	}
}
void Dp(int u) {
	g[u][1]=a[u];
	if(son[u]) {
		Dp(son[u]);f[u][0]=f[son[u]][1];f[u][1]=min(f[son[u]][0],f[son[u]][1]);
	}
	for(int i=head[u];i;i=nxt[i]) {
		int v=to[i];if(v==fa[u]||v==son[u])continue;
		Dp(v);g[u][0]+=f[v][1];g[u][1]+=min(f[v][0],f[v][1]);
	}
	f[u][0]+=g[u][0],f[u][1]+=g[u][1];
}
struct par {ll _0,_1;};
par Ask(int x) {
	matr ans=Query(1,dfn[x],dfn[ed[x]]);
	return (par){min(ans.z1,ans.z2),min(ans.z3,ans.z4)};
}
void Change(int v,ll y) {
	g[v][1]+=y;
//	printf("%d %lld\n",v,g[v][1]);
	while(v) {
		Update(1,dfn[v],v);
		int u=top[v];
		par nw=Ask(u);
		v=fa[u];
		g[v][0]+=nw._1-f[u][1];g[v][1]+=min(nw._0,nw._1)-min(f[u][1],f[u][0]);
		f[u][0]=nw._0,f[u][1]=nw._1;
//		printf("%d: %lld %lld\n",u,f[u][0],f[u][1]);
	}
}

int main() {
	char ch[5];
	scanf("%d%d%s",&n,&m,ch);
	for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
	for(int i=1;i<n;i++) {int u,v;scanf("%d%d",&u,&v);add_edge(u,v),add_edge(v,u);}
	gt_son(1),gt_top(1,1);Dp(1);Build(1,1,n);
//	printf("%lld %lld\n",f[1][0],f[1][1]);
	for(int i=1;i<=m;i++) {
		int A,B,cc;ll x,y;
		scanf("%d%lld%d%lld",&A,&x,&B,&y);cc=x+y;
		x=!x?inf:-inf;y=!y?inf:-inf;
//		printf("%lld %lld\n",x,y);
		Change(A,x),Change(B,y);
		ll ans=min(f[1][0],f[1][1])+cc*inf;
		if(ans>=inf) printf("-1\n");
		else printf("%lld\n",ans);
		Change(A,-x),Change(B,-y);
	}
	return 0;
}