• luoguP4719 【模板】动态 DP


    题意

    我理解的动态DP:
    发现DP可以写成矩阵的形式,因此用数据结构维护矩阵乘积。

    对于这道题,显然有DP:
    (f_{x,0/1})表示(x)的子树中,x选/不选的最大点独立集。

    (f_{x,0}=sumlimits_{yin son_x}max(f_{y,0},f_{y,1}),f_{x,1}=sumlimits_{yin sno_x}f_{y,0}+a_x)

    既然在树上,就用树剖或者LCT解决,本质都是将树拆成链,这里用树剖。

    (son_x)表示(x)的重儿子,(g_{x,0/1})表示除去(son_x)后的(f_{x,0})的值。

    有:
    (f_{x,0}=g_{x,0}+max(f_{son_x,0},f_{son_x,1}),f_{x,1}=g_{x,1}+f_{son_x,0}),注意(g_{x,1})初值为(a_x)

    DP写成矩阵的形式:
    (egin{bmatrix}g_{x,0}&g_{x,0}\g_{x,1}& 0end{bmatrix}egin{bmatrix}f_{y,0}\ f_{y,1}end{bmatrix}=egin{bmatrix}f_{x,0}\ f_{x,1}end{bmatrix})

    注意这里的矩乘长这样:

    Mat operator*(Mat a,Mat b)
    {
    	Mat res;
    	for(int i=1;i<=2;i++)
    		for(int j=1;j<=2;j++)
    			for(int k=1;k<=2;k++)
    				res[i][j]=max(res[i][j],a[i][k]+b[k][j]);
    	return res;
    } 
    

    之后就正常树剖修改查询即可

    code:

    #include<bits/stdc++.h>
    using namespace std;
    #define ls(p) (p<<1)
    #define rs(p) (p<<1|1)
    const int maxn=1e5+10;
    int n,m,cnt,tim;
    int head[maxn],a[maxn],size[maxn],pre[maxn],dep[maxn],son[maxn],dfn[maxn],pos[maxn],top[maxn],ed[maxn];
    int f[maxn][2];
    struct edge{int to,nxt;}e[maxn<<1];
    struct Mat
    {
    	int a[5][5];
    	Mat(){memset(a,-0x3f,sizeof(a));}
    	int* operator[](int i){return a[i];}
    }val[maxn],seg[maxn<<2];
    Mat operator*(Mat a,Mat b)
    {
    	Mat res;
    	for(int i=1;i<=2;i++)
    		for(int j=1;j<=2;j++)
    			for(int k=1;k<=2;k++)
    				res[i][j]=max(res[i][j],a[i][k]+b[k][j]);
    	return res;
    } 
    inline void add(int u,int v)
    {
    	e[++cnt].nxt=head[u];
    	head[u]=cnt;
    	e[cnt].to=v;
    }
    void dfs1(int x,int fa)
    {
    	dep[x]=dep[fa]+1;pre[x]=fa;size[x]=1;
    	for(int i=head[x];i;i=e[i].nxt)
    	{
    		int y=e[i].to;
    		if(y==fa)continue;
    		dfs1(y,x);size[x]+=size[y];
    		if(size[son[x]]<size[y])son[x]=y;
    	}
    }
    void dfs2(int x,int tp)
    {
    	dfn[x]=++tim;pos[tim]=x;top[x]=tp;ed[tp]=max(ed[tp],tim);
    	f[x][0]=0,f[x][1]=a[x];
    	val[x][1][1]=val[x][1][2]=0;
    	val[x][2][1]=a[x];
    	if(son[x])
    	{
    		dfs2(son[x],tp);
    		f[x][0]+=max(f[son[x]][0],f[son[x]][1]);
    		f[x][1]+=f[son[x]][0];
    	}
    	for(int i=head[x];i;i=e[i].nxt)
    	{
    		int y=e[i].to;
    		if(y==pre[x]||y==son[x])continue;
    		dfs2(y,y);
    		f[x][0]+=max(f[y][0],f[y][1]);
    		f[x][1]+=f[y][0];
    		val[x][1][1]+=max(f[y][0],f[y][1]);
    		val[x][1][2]=val[x][1][1];
    		val[x][2][1]+=f[y][0];
    	}
    }
    inline void up(int p){seg[p]=seg[ls(p)]*seg[rs(p)];}
    void build(int p,int l,int r)
    {
    	if(l==r){seg[p]=val[pos[l]];return;}
    	int mid=(l+r)>>1;
    	build(ls(p),l,mid);build(rs(p),mid+1,r);
    	up(p);
    }
    void change(int p,int l,int r,int k)
    {
    	if(l==r){seg[p]=val[pos[k]];return;}
    	int mid=(l+r)>>1;
    	if(k<=mid)change(ls(p),l,mid,k);
    	else change(rs(p),mid+1,r,k);
    	up(p); 
    }
    Mat query(int p,int l,int r,int ql,int qr)
    {
    	if(l>=ql&&r<=qr)return seg[p];
    	int mid=(l+r)>>1;
    	if(qr<=mid)return query(ls(p),l,mid,ql,qr);
    	else if(ql>mid)return query(rs(p),mid+1,r,ql,qr);
    	else return query(ls(p),l,mid,ql,qr)*query(rs(p),mid+1,r,ql,qr);
    }
    inline void trchange(int x,int k)
    {
    	val[x][2][1]+=k-a[x];
    	a[x]=k;
    	Mat tmp1,tmp2;
    	while(x)
    	{
    		tmp1=query(1,1,n,dfn[top[x]],ed[top[x]]);
    		change(1,1,n,dfn[x]);
    		tmp2=query(1,1,n,dfn[top[x]],ed[top[x]]);	
    		x=pre[top[x]];
    		val[x][1][1]+=max(tmp2[1][1],tmp2[2][1])-max(tmp1[1][1],tmp1[2][1]);
    		val[x][1][2]=val[x][1][1];
    		val[x][2][1]+=tmp2[1][1]-tmp1[1][1];
    	}
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	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);
    		add(u,v),add(v,u);
    	}
    	dfs1(1,0);dfs2(1,1);
    	build(1,1,n);
    	for(int i=1;i<=m;i++)
    	{
    		int x,y;scanf("%d%d",&x,&y);
    		trchange(x,y);
    		a[x]=y;
    		Mat res=query(1,1,n,dfn[1],ed[1]);
    		printf("%d
    ",max(res[1][1],res[2][1]));
    	}
    	return 0;
    }
    
  • 相关阅读:
    ORB Test Hanson
    ajax异步传输中的乱码问题
    调用淘宝API遇到的问题
    doc命令查看电脑配置大全
    从关联数组中取得键名
    php图片上传
    doc命令查看电脑配置
    一个空间配置多个虚拟主机
    淘客网站中系统信息获取
    opendir(path,context)
  • 原文地址:https://www.cnblogs.com/nofind/p/11994988.html
Copyright © 2020-2023  润新知