- 思路:
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;
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;
}
}
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);
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;
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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了