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;
}

猜你喜欢

转载自blog.csdn.net/liufengwei1/article/details/111052647
今日推荐