P4719 【模板】"动态 DP"&动态树分治

动态树形dp模板题

首先有sigma肯定不能矩阵优化了。

于是我们定义g(x)表示轻儿子的全部贡献,这样每一次修改只会修改logn次g(重链剖分的性质)

由于dp边界在叶子结点,我们需要记录每一条重链的结束位置。

用线段树统计一路上来矩阵乘法的值,该修改的修改最后询问根就是答案了。

(还是序列上的简单awa)

#include<bits/stdc++.h>
using namespace std;
#define orz cout<<"lyakioi!!!!!!!!!!!!!!!!!"<<endl
inline int r(){int s=0,k=1;char c=getchar();while(!isdigit(c)){if(c=='-')k=-1;c=getchar();}while(isdigit(c)){s=s*10+c-'0';c=getchar();}return s*k;}
struct matrix
{
	int a[3][3];
	matrix()
	{
		for(int i=1;i<=2;i++)
		for(int j=1;j<=2;j++)
		a[i][j]=-1e9;
	}
	int* operator[](int x)
	{
		return a[x];
	}
};
int cnt,m,times,n,deep[1000001],fa[1000001],top[1000001],ed[1000001],head[1000001],w[1000001],b[1000001],id[1000001],size[1000001],son[1000001],f[1000001][2];
struct node
{
	int to,next;
}a[1000001];
matrix ma[150001];
matrix tr[500001];
void add_edge(int from,int to)
{
	a[++cnt].to=to;
	a[cnt].next=head[from];
	head[from]=cnt;
}
void dfs1(int u,int father,int deeps)
{
	size[u]=1;
	int maxi=0;
	deep[u]=deeps;
	fa[u]=father;
	f[u][1]=w[u];
	for(int i=head[u];i;i=a[i].next)
	{
		int v=a[i].to;
		if(v==father)continue;
		dfs1(v,u,deeps+1);
		if(maxi<size[v])
		{
			maxi=size[v];
			son[u]=v;
		}
		size[u]+=size[v];
		f[u][1]+=f[v][0];
		f[u][0]+=max(f[v][1],f[v][0]);
	}
}
void dfs2(int u,int tp)
{
	times++;
	top[u]=tp;
	ed[top[u]]=u;
	id[u]=times;
	b[times]=u;
	ma[u][2][1]=w[u];
	ma[u][2][2]=-1e9;
	ma[u][1][1]=0;
	if(son[u])dfs2(son[u],tp);
	for(int i=head[u];i;i=a[i].next)
	{
		int v=a[i].to;
		if(id[v])continue;
		dfs2(v,v);
		ma[u][1][1]+=max(f[v][0],f[v][1]);
		ma[u][2][1]+=f[v][0];
	}
	ma[u][1][2]=ma[u][1][1];
}
matrix mul(matrix x,matrix y)
{
	matrix ans;
	for(int k=1;k<=2;k++)
	for(int i=1;i<=2;i++)
	for(int j=1;j<=2;j++)
	ans[i][j]=max(ans[i][j],x[i][k]+y[k][j]);
	return ans;
}
void build(int l,int r,int bh)
{
	if(l==r)
	{
		tr[bh]=ma[b[l]];
		return;
	}
	int mid=(l+r)/2;
	build(l,mid,bh*2);
	build(mid+1,r,bh*2+1);
	tr[bh]=mul(tr[bh*2],tr[bh*2+1]);
}
void change(int l,int r,int bh,int k)
{
//	cout<<"I CAN'T STOP!\n";
	if(l>k||r<k)return;
	if(l==r)
	{
		tr[bh]=ma[b[l]];
		return;
	}
	int mid=(l+r)/2;
	change(l,mid,bh*2,k);
	change(mid+1,r,bh*2+1,k);
	tr[bh]=mul(tr[bh*2],tr[bh*2+1]);
}
matrix sum(int now_l,int now_r,int bh,int l,int r)
{
//	cout<<"GG\n"<<now_l<<" "<<now_r<<" "<<l<<" "<<r<<endl;
	if(l<=now_l&&now_r<=r)return tr[bh];
	int mid=(now_l+now_r)/2;
	if(r<=mid)return sum(now_l,mid,bh*2,l,r);
	if(l>mid)return sum(mid+1,now_r,bh*2+1,l,r);
	return mul(sum(now_l,mid,bh*2,l,r),sum(mid+1,now_r,bh*2+1,l,r));
}
void tr_change(int x,int y)
{
	ma[x][2][1]+=y-w[x];w[x]=y;
	while(x)
	{
//		cout<<x<<endl;
		matrix A=sum(1,n,1,id[top[x]],id[ed[top[x]]]);
		change(1,n,1,id[x]);
		matrix B=sum(1,n,1,id[top[x]],id[ed[top[x]]]);
		x=fa[top[x]];
		ma[x][1][1]+=max(B[1][1],B[2][1])-max(A[1][1],A[2][1]);
		ma[x][1][2]=ma[x][1][1];
		ma[x][2][1]+=B[1][1]-A[1][1];
	}
}
int main()
{ 
	n=r();m=r();
	for(int i=1;i<=n;++i)w[i]=r();
	for(int i=1;i<n;i++)
	{
		int u=r(),v=r();
		add_edge(u,v);
		add_edge(v,u);
	}
	dfs1(1,0,1);
	dfs2(1,1);
	build(1,n,1);
//	cout<<"NONE\n"
	while(m--)
	{
		int u=r(),w=r();
		tr_change(u,w);
		matrix ans=sum(1,n,1,id[top[1]],id[ed[top[1]]]);
		printf("%d\n",max(ans[1][1],ans[2][1]));
	}
	return 0;
}
posted @ 2021-09-03 18:41  lei_yu  阅读(31)  评论(0编辑  收藏  举报