l洛谷P4719 【模板】“动态 DP“&动态树分治
作者:互联网
https://www.luogu.com.cn/problem/P4719
学习自https://www.luogu.com.cn/blog/Tweetuzki/solution-p4179
题解中有些实现方面的细节没讲,我看了代码才理解的。。。
就是把g分出来以后,树上的一条重链是整个top到end一起计算的,然后把这一段的值去更新fa[top]的g也就是更新val数组
由于只有log段,每次又要把这一段整段的matrix值算出来也就是qry整段,再更新上面一个点的g,复杂度是log^2的
#include<bits/stdc++.h>
using namespace std;
const int maxl=3e5+10;
const int inf=1e9;
struct matrix
{
int a[3][3];
matrix()
{
for(int i=0;i<2;i++)for(int j=0;j<2;j++) a[i][j]=-inf;
}
matrix operator * (const matrix &b)const
{
matrix ret;
for(int i=0;i<2;i++)for(int j=0;j<2;j++)for(int k=0;k<2;k++)
ret.a[i][k]=max(ret.a[i][k],a[i][j]+b.a[j][k]);
return ret;
}
};
int n,q,cnt;
int a[maxl],tot[maxl],son[maxl],dep[maxl];
int top[maxl],fa[maxl],idx[maxl],dy[maxl],rend[maxl];
int f[maxl][2];
struct node
{
int l,r;
matrix a;
}tr[maxl*4];
vector<int> e[maxl];
matrix val[maxl];
inline void dfs1(int u,int f)
{
dep[u]=dep[f]+1;fa[u]=f;tot[u]=1;son[u]=0;
for(int v:e[u])
if(v!=f)
{
dfs1(v,u);
tot[u]+=tot[v];
if(tot[v]>tot[son[u]])
son[u]=v;
}
}
inline void dfs2(int u,int topf)
{
idx[u]=++cnt;dy[cnt]=u;top[u]=topf;
rend[topf]=max(rend[topf],cnt);
f[u][0]=0;f[u][1]=a[u];
val[u].a[0][0]=val[u].a[0][1]=0;
val[u].a[1][0]=a[u];
if(!son[u]) return;
dfs2(son[u],topf);
f[u][0]+=max(f[son[u]][0],f[son[u]][1]);
f[u][1]+=f[son[u]][0];
for(int v:e[u])
if(!idx[v])
{
dfs2(v,v);
f[u][0]+=max(f[v][0],f[v][1]);
f[u][1]+=f[v][0];
val[u].a[0][0]+=max(f[v][0],f[v][1]);
val[u].a[0][1]=val[u].a[0][0];
val[u].a[1][0]+=f[v][0];
}
}
inline void push_up(int k)
{
tr[k].a=tr[k<<1].a*tr[k<<1|1].a;
}
inline void build(int k,int l,int r)
{
tr[k].l=l;tr[k].r=r;
if(l==r)
{
tr[k].a=val[dy[l]];
return;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
push_up(k);
}
inline void prework()
{
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<n;i++)
{
int u,v;scanf("%d%d",&u,&v);
e[u].push_back(v);
e[v].push_back(u);
}
dfs1(1,0);
dfs2(1,1);
build(1,1,n);
}
inline void upd(int k,int l)
{
if(tr[k].l==tr[k].r)
{
tr[k].a=val[dy[l]];
return;
}
int mid=(tr[k].l+tr[k].r)>>1;
if(l<=mid)
upd(k<<1,l);
else
upd(k<<1|1,l);
push_up(k);
}
inline matrix qry(int k,int l,int r)
{
if(tr[k].l==l && tr[k].r==r)
return tr[k].a;
int mid=(tr[k].l+tr[k].r)>>1;
if(r<=mid)
return qry(k<<1,l,r);
else if(l>mid)
return qry(k<<1|1,l,r);
else
return qry(k<<1,l,mid)*qry(k<<1|1,mid+1,r);
}
inline void upd_path(int u,int w)
{
val[u].a[1][0]+=w-a[u];
a[u]=w;
matrix bef,aft;
while(u!=0)
{
bef=qry(1,idx[top[u]],rend[top[u]]);
upd(1,idx[u]);
aft=qry(1,idx[top[u]],rend[top[u]]);
int f=fa[top[u]];
val[f].a[0][0]+=max(aft.a[0][0],aft.a[1][0])-max(bef.a[0][0],bef.a[1][0]);
val[f].a[0][1]=val[f].a[0][0];
val[f].a[1][0]+=aft.a[0][0]-bef.a[0][0];
u=f;
}
}
inline void mainwork()
{
for(int i=1;i<=q;i++)
{
int x,y;
scanf("%d%d",&x,&y);
upd_path(x,y);
matrix ans=qry(1,idx[1],rend[1]);
printf("%d\n",max(ans.a[0][0],ans.a[1][0]));
}
}
int main()
{
prework();
mainwork();
return 0;
}
标签:洛谷,matrix,val,int,tot,son,topf,动态,P4719 来源: https://blog.csdn.net/liufengwei1/article/details/111052647