luoguP4719 【模板】动态 DP 线段树_树链剖分_矩阵乘法_动态DP

Code:

#include<bits/stdc++.h> 
#define setIO(s) freopen(s".in","r",stdin) 
#define maxn 300000 
#define lson (now<<1) 
#define rson ((now<<1)|1) 
#define ll long long 
const ll inf = 1e17; 
using namespace std;
int hd[maxn],to[maxn],nex[maxn],V[maxn],hson[maxn],fa[maxn],dfn[maxn], ln[maxn],F[maxn][2],siz[maxn],top[maxn],bot[maxn]; 
int edges,tim,n,Q; 
void add(int u,int v)
{
	nex[++edges]=hd[u],hd[u]=edges,to[edges]=v; 
}
void dfs1(int u,int ff)
{
	siz[u]=1,fa[u]=ff; 
	for(int i=hd[u];i;i=nex[i])
	{
		if(to[i]==ff) continue; 
		dfs1(to[i],u); 
		siz[u]+=siz[to[i]]; 
		if(siz[to[i]] > siz[hson[u]]) hson[u]=to[i]; 
	}
}
void dfs2(int u,int tp)
{
	top[u]=tp,ln[++tim]=u,dfn[u]=tim; 
	if(hson[u]) 
		dfs2(hson[u], tp), bot[u]=bot[hson[u]]; 
	else 
		bot[u]=u; 
	for(int i=hd[u];i;i=nex[i])
	{
		if(to[i]==fa[u]||to[i]==hson[u]) continue; 
		dfs2(to[i],to[i]);  
	}
}
void dfs(int u)
{
	F[u][0]=0,F[u][1]=V[u]; 
	for(int i=hd[u];i;i=nex[i])
	{
		if(to[i]==fa[u]) continue; 
		dfs(to[i]); 
		F[u][0]+=max(F[to[i]][1],F[to[i]][0]); 
		F[u][1]+=F[to[i]][0]; 
	}
}
struct Matrix
{
	ll a[2][2]; 
	ll*operator[](int x){ return a[x]; }
}t[maxn<<1],tmp[maxn<<1]; 
Matrix operator*(Matrix a,Matrix b)
{
	Matrix c; 
	c[0][0]=max(a[0][0]+b[0][0],a[0][1]+b[1][0]); 
	c[0][1]=max(a[0][0]+b[0][1],a[0][1]+b[1][1]); 
	c[1][0]=max(a[1][0]+b[0][0],a[1][1]+b[1][0]); 
	c[1][1]=max(a[1][0]+b[0][1],a[1][1]+b[1][1]);      
	return c; 
}
void Build(int now,int l,int r)
{
	if(l==r)
	{
		int u=ln[l];  
		ll g0=0,g1=V[u]; 
		for(int i=hd[u];i;i=nex[i])
		{
			int v=to[i];
			if(v==fa[u]||v==hson[u]) continue; 
			g0+=max(F[v][0],F[v][1]); 
			g1+=F[v][0]; 
		}
		t[now]=tmp[l]=(Matrix) {g0,g0,g1,-inf}; 
		return; 
	}
	int mid=(l+r)>>1; 
	Build(lson,l,mid),Build(rson,mid+1,r); 
	t[now]=t[lson]*t[rson]; 
}
void Modify(int now,int l,int r,int p)
{
	if(l==r) 
	{
	    t[now]=tmp[l]; 
	    return;  
	}
	int mid=(l+r)>>1; 
	if(p<=mid) Modify(lson,l,mid,p); 
	else Modify(rson,mid+1,r,p); 
	t[now]=t[lson]*t[rson]; 
}
Matrix Query(int now,int l,int r,int L,int R)
{
	if(L==l&&r==R) return t[now];
	int mid=(l+r)>>1; 
	if(R<=mid) return Query(lson,l,mid,L,R); 
	if(L>mid) return Query(rson,mid+1,r,L,R); 
	return Query(lson,l,mid,L,mid)*Query(rson,mid+1,r,mid+1,R); 
}
void Update(int u,int w)
{
	tmp[dfn[u]][1][0]+=w-V[u],V[u]=w; 
	while(u)
	{
		Matrix a=Query(1,1,n,dfn[top[u]],dfn[bot[u]]); 
		Modify(1,1,n,dfn[u]); 
		Matrix b=Query(1,1,n,dfn[top[u]],dfn[bot[u]]); 
		u=fa[top[u]];
		if(!u) break; 
		int x = dfn[u]; 
		ll g0=a[0][0],g1=a[1][0],f0=b[0][0],f1=b[1][0]; 
		tmp[x][0][0]=tmp[x][0][1]=tmp[x][0][0]+max(f0,f1)-max(g0,g1); 
		tmp[x][1][0]=tmp[x][1][0]+f0-g0; 
	}
}
int main()
{
	// setIO("input"); 
	scanf("%d%d",&n,&Q); 
	for(int i=1;i<=n;++i) scanf("%d",&V[i]); 
	for(int i=1,u,v;i<n;++i) 
	{
		scanf("%d%d",&u,&v),add(u,v),add(v,u); 
	}
	dfs1(1,0),dfs2(1,1),dfs(1),Build(1,1,n); 
	while(Q--)
	{
		int x,w; 
		scanf("%d%d",&x,&w);
		Update(x,w); 
		Matrix ans=Query(1,1,n,dfn[1],dfn[bot[1]]);                
		printf("%lld\n",max(ans[0][0],ans[1][0])); 
	}
	return 0; 
}

  

上一篇:有关 Telegram(电报) 的一些知识


下一篇:Java多线程学习——synchronized锁机制