ddp就是通过加法对min/max的分配率把原来不好维护的dp转移搞成可以遵循分配率的矩阵形式,自然就以用一些数据结构去维护
比如说这题求最大权独立集
先写出转移方程
dp[u][0/1]表示该点取或者不取时该点为根的子树的最大权独立集
dp[u][0]=
max(dp[v][0],dp[v][1])
dp[u][1]=(
dp[v][0]) +val[u]
数据结构维护的话就是LCT或者树链剖分
LCT好久不写了懒得写,就想想树剖吧
考虑线段树上查询的一个区间关系大抵是父亲和重儿子
那么就令g[u][0]表示该点不选时除重儿子以外的dp值之和
g[u][0]=
max(dp[v][0],dp[v][1])
g[u][1]=(
dp[v][0])+val[u]
重写转移方程
dp[u][0]=max(dp[son][0],dp[son][1])+g[u][0]
dp[u][1]=dp[son][0]+g[u][1]
写出矩阵
显然每次的答案都是max(dp[1][0],dp[1][1])
更新的话,每次显然只会改变log个从一条链跳入另一条链的g值
所以直接按照跳top的父亲,改,再跳,再改,这样的套路就可以了
跳的复杂度是log,修改是log总复杂度两只log
用LCT或者GBT可以弄到一只log,但博主太菜并不会
代码又臭又长
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define lson root<<1
#define rson root<<1|1
#define N 400040
using namespace std;
struct matrix
{
int a[2][2];
matrix()
{
a[0][0]=a[0][1]=a[1][0]=a[1][1]=-inf;
}
}m[N];
inline void mx(int &a,const int &b)
{
if(a<b) a=b;
}
void print(matrix a)
{
for(int i=0;i<=1;i++)
{
for(int j=0;j<=1;j++)
{
printf("%d ",a.a[i][j]);
}
puts("");
}
}
matrix mul(matrix a,matrix b)
{
matrix c;
for(int i=0;i<=1;i++)
{
for(int j=0;j<=1;j++)
{
for(int k=0;k<=1;k++)
{
mx(c.a[i][j],a.a[i][k]+b.a[k][j]);
}
}
}
return c;
}
vector<int> g[N];
int l[N],r[N],p[N];
int gg[N][2],f[N][2],idn[N],id[N],top[N],fa[N],sz[N],son[N],v[N],w[N],ed[N],cnt;
void push_up(int root)
{
m[root]=mul(m[lson],m[rson]);
}
void build(int root,int ll,int rr)
{
l[root]=ll,r[root]=rr;
if(ll==rr)
{
m[root].a[0][0]=m[root].a[0][1]=gg[idn[ll]][0];
m[root].a[1][0]=gg[idn[ll]][1];
p[ll]=root;
return ;
}
int mid=(ll+rr)>>1;
build(lson,ll,mid);
build(rson,mid+1,rr);
push_up(root);
}
void update(int root,int pos,int val)
{
if(l[root]==r[root])
{
m[root].a[1][0]+=val-w[l[root]];
w[l[root]]=val;
return ;
}
int mid=(l[root]+r[root])>>1;
if(pos<=mid)
{
update(lson,pos,val);
}
else
{
update(rson,pos,val);
}
push_up(root);
}
void update2(int root,int pos,int val1,int val2,int val3,int val4)
{
if(pos<1) return;
if(l[root]==r[root])
{
m[root].a[0][0]+=val2-val1;
m[root].a[0][1]=m[root].a[0][0];
m[root].a[1][0]+=val4-val3;
return ;
}
int mid=(l[root]+r[root])>>1;
if(pos<=mid)
{
update2(lson,pos,val1,val2,val3,val4);
}
else
{
update2(rson,pos,val1,val2,val3,val4);
}
push_up(root);
}
matrix query(int root,int ll,int rr)
{
if(ll<=l[root]&&r[root]<=rr)
{
return m[root];
}
int mid=(l[root]+r[root])>>1;
if(rr<=mid)
{
return query(lson,ll,rr);
}
else
{
if(mid<ll)
{
return query(rson,ll,rr);
}
return mul(query(lson,ll,mid),query(rson,mid+1,rr));
}
}
void dfs1(int now,int f)
{
fa[now]=f;
sz[now]=1;
int maxson=-1;
for(int i=0;i<g[now].size();i++)
{
if(g[now][i]==f) continue;
dfs1(g[now][i],now);
sz[now]+=sz[g[now][i]];
if(sz[g[now][i]]>maxson)
{
maxson=sz[g[now][i]];
son[now]=g[now][i];
}
}
}
void dfs2(int now,int tp)
{
id[now]=++cnt;
top[now]=tp;
w[cnt]=v[now];
idn[cnt]=now;
if(!son[now]) {f[now][1]=v[now],gg[now][1]=v[now],ed[now]=now;return ;}
dfs2(son[now],tp);
for(int i=0;i<g[now].size();i++)
{
if(g[now][i]==fa[now]||g[now][i]==son[now]) continue;
dfs2(g[now][i],g[now][i]);
gg[now][0]+=max(f[g[now][i]][0],f[g[now][i]][1]);
gg[now][1]+=f[g[now][i]][0];
}
gg[now][1]+=v[now];
f[now][0]=gg[now][0]+max(f[son[now]][0],f[son[now]][1]);
f[now][1]=gg[now][1]+f[son[now]][0];
ed[now]=ed[son[now]];
}
void change(int now,int val)
{
int max1,max2,f1,f2;
matrix pre=query(1,id[top[now]],id[ed[now]]);
update(1,id[now],val);
matrix c=query(1,id[top[now]],id[ed[now]]);
now=fa[top[now]];
max1=max(pre.a[1][0],pre.a[0][0]);
max2=max(c.a[1][0],c.a[0][0]);
f1=pre.a[0][0];
f2=c.a[0][0];
while(top[now])
{
pre=query(1,id[top[now]],id[ed[now]]);
update2(1,id[now],max1,max2,f1,f2);
c=query(1,id[top[now]],id[ed[now]]);
max1=max(pre.a[1][0],pre.a[0][0]);
max2=max(c.a[1][0],c.a[0][0]);
f1=pre.a[0][0];
f2=c.a[0][0];
now=fa[top[now]];
}
}
int n,q;
int main()
{
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
{
scanf("%d",&v[i]);
}
int from,to;
for(int i=1;i<n;i++)
{
scanf("%d%d",&from,&to);
g[from].push_back(to);
g[to].push_back(from);
}
dfs1(1,0);
dfs2(1,1);
build(1,1,cnt);
int pp,vv;
matrix tmp;
for(int i=1;i<=q;i++)
{
scanf("%d%d",&pp,&vv);
change(pp,vv);
tmp=query(1,id[top[1]],id[ed[1]]);
printf("%d\n",max(tmp.a[0][0],tmp.a[1][0]));
}
}