zoukankan      html  css  js  c++  java
  • 洛谷P4719 【模板】"动态 DP"&动态树分治

    日常懵逼

    先不考虑修改,就是一个很基础的没有上司的舞会。

    定义状态(f[i][0/1])表示以(i)为根且 不选/选 (i)的最大权独立集

    显然有转移:

    (f[u][0]=sum max(f[v][0],f[v][1]))

    (f[u][1]=sum f[v][0] + a[u])

    考虑修改时,只会对她上面的链上的节点产生影响。

    由于树可能会退化成一条链,那么修改一次更新的时间复杂度就是(O(n)),不可接受。

    所以需要用重链剖分。

    重链剖分有以下性质能够保证快速修改:
    1.每个点到根的路径上,最多经过(log(n))条轻边,那么重链最多(log(n))条,保证时间复杂度

    2.重链剖分中,一条重链在剖出的(dfn)上是连续的一段区间,保证可以用数据结构维护,能够快速转移。

    3.每条重链的链尾都是叶节点,而且只有叶节点没有重儿子,保证了状态转移方向。

    我们先做一个树剖,然后一条重链,一条重链地进行(dp)

    然后设(g[i][0/1])表示只考虑轻儿子的(dp)

    有如下转移:

    (f[i][0]=max(f[hson][0],f[hson][1])+g[i][0])

    (f[i][1]=f[hson][0]+g[i][1])

    然后可以写出矩阵的形式:

    [egin{bmatrix} f[i][0] \ f[i][1] \ end{bmatrix} = egin{bmatrix} g[i][0] &g[i][0] \ g[i][1] & -∞ \ end{bmatrix} imes egin{bmatrix} f[hson][0] \ f[hson][1] \ end{bmatrix} ]

    然后就可以树剖+线段树维护,修改时改重链(f[])链顶(g[])就可以了。

    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    #include<iostream>
    #include<cstdio>
    using namespace std;
    #define N 100005
    #define INF 0x3f3f3f3f
    #define LL long long
    int rd()
    {
    	int x=0,f=1;char c=getchar();
    	while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
    	while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48); c=getchar();}
    	return f*x;
    }
    int n;
    struct Matrix{
    	int m[3][3];
    	int* operator [](int i){ return m[i]; }
    };
    Matrix operator * (Matrix a,Matrix b)
    {
    	Matrix c;
    	for(int i=1;i<=2;i++)
    		for(int j=1;j<=2;j++)
    			c[i][j]=-INF;
    	for(int i=1;i<=2;i++)
    		for(int k=1;k<=2;k++)
    			for(int j=1;j<=2;j++)
    				c[i][j]=max(c[i][j],a[i][k]+b[k][j]);
    	return c;
    }
    Matrix tree[N<<2],g[N];
    vector<int>G[N];
    int a[N],fat[N],siz[N],hson[N],dep[N];
    int tp[N],ed[N],dfn[N],tid[N],dfc;
    int f[N][2];//f[i][1]以i为根且i选的最大权独立集 f[i][0]不选i 
    void dfs(int u,int fa)
    {
    	int mx=0;
    	fat[u]=fa;
    	siz[u]=1;
    	for(int i=0;i<G[u].size();i++)
    	{
    		int v=G[u][i];
    		if(v==fa) continue;
    		dfs(v,u);
    		siz[u]+=siz[v];
    		if(siz[v]>mx)
    			mx=siz[v],hson[u]=v;
    	}
    }
    void dfs2(int u,int Top)
    {
    	dfc++;
    	dfn[u]=dfc;
    	tid[dfn[u]]=u;
    	tp[u]=Top;
    	ed[tp[u]]=dfn[u];
    	f[u][0]=g[u][1][1]=0;
    	f[u][1]=g[u][2][1]=a[u];
    	if(hson[u])
    	{
    		dfs2(hson[u],Top);
    		f[u][1]+=f[hson[u]][0];
    		f[u][0]+=max(f[hson[u]][0],f[hson[u]][1]);
    	}
    	for(int i=0;i<G[u].size();i++)
    	{
    		int v=G[u][i];
    		if(v==fat[u]||v==hson[u]) continue;
    		dfs2(v,v);
    		g[u][2][1]+=f[v][0],g[u][1][1]+=max(f[v][0],f[v][1]);
    		f[u][1]+=f[v][0],f[u][0]+=max(f[v][0],f[v][1]);
    	}
    	g[u][1][2]=g[u][1][1];
    }
    void PushUp(int i)
    {
    	tree[i]=tree[i<<1]*tree[i<<1|1];
    }
    void Build(int i,int l,int r)
    {
    	if(l==r)
    	{
    		tree[i]=g[tid[l]];
    		return ;
    	}
    	int mid=(l+r)>>1;
    	Build(i<<1,l,mid);
    	Build(i<<1|1,mid+1,r);
    	PushUp(i);
    }
    void Update(int i,int l,int r,int pos)
    {
    	if(l==r)
    	{
    		tree[i]=g[tid[pos]];
    		return ;
    	}
    	int mid=(l+r)>>1;
    	if(pos<=mid) Update(i<<1,l,mid,pos);
    	else Update(i<<1|1,mid+1,r,pos);
    	PushUp(i);
    } 
    Matrix Query(int i,int l,int r,int ql,int qr)
    {
    	if(ql<=l&&r<=qr) return tree[i];
    	int mid=(l+r)>>1;
    	if(qr<=mid) return Query(i<<1,l,mid,ql,qr);
    	else if(ql>mid) return Query(i<<1|1,mid+1,r,ql,qr);
    	return Query(i<<1,l,mid,ql,qr)*Query(i<<1|1,mid+1,r,ql,qr);
    }
    void Modify(int u,int val)
    {
    	g[u][2][1]+=val-a[u],a[u]=val;
    	while(u)
    	{
    		Matrix x=Query(1,1,n,dfn[tp[u]],ed[tp[u]]);
    		Update(1,1,n,dfn[u]);
    		Matrix y=Query(1,1,n,dfn[tp[u]],ed[tp[u]]);
    		u=fat[tp[u]];
    		g[u][1][1]+=max(y[1][1],y[2][1])-max(x[1][1],x[2][1]);
    		g[u][1][2]=g[u][1][1];
    		g[u][2][1]+=y[1][1]-x[1][1]; 
    	}
    }
    int main()
    {
    	n=rd();int Q=rd();
    	for(int i=1;i<=n;i++)
    		a[i]=rd();
    	for(int i=1;i<=n-1;i++)
    	{
    		int u=rd(),v=rd();
    		G[u].push_back(v);
    		G[v].push_back(u);
    	}
    	dfs(1,0);
    	dfs2(1,1);
    	Build(1,1,n);
    	while(Q--)
    	{
    		int u=rd(),val=rd();
    		Modify(u,val);
    		Matrix ans=Query(1,1,n,1,ed[1]);
    		printf("%d
    ",max(ans[1][1],ans[2][1]));
    	}
        return 0;
    }
    
  • 相关阅读:
    Java8性能优化之字符串拼接
    Java8字符串分割的几种方式及性能比较
    【Collections:集合工具类:常用方法】
    【ArrayList嵌套HashMap】
    【集合工具类:Collections】
    【HashMap 嵌套 HashMap】
    【HashMap 嵌套 ArrayList】
    【TreeMapDemo】
    【LinkedHashMap】
    【TreeMap】
  • 原文地址:https://www.cnblogs.com/lyttt/p/13395949.html
Copyright © 2011-2022 走看看