[动态dp][矩阵乘法][树链剖分][线段树] Luogu P4719 【模板】动态dp
作者:互联网
题解
- 动态dp模板题,矩阵乘法有所不同C=A*B=max(a[i][j]+b[j][k])
代码
1 #include <cstdio> 2 #include <iostream> 3 using namespace std; 4 const int N=1e5+1,inf=999999999; 5 struct matrix 6 { 7 int a[3][3]; 8 void init() { for (int i=0;i<2;i++) for (int j=0;j<2;j++) a[i][j]=-inf; } 9 }ans,last,front,T[N*4],val[N]; 10 struct edge{ int to,from; }e[N*2]; 11 struct Tree{ int size,id,fa,top,son,deep,end; }t[N*2]; 12 int n,m,cnt,tot,ldp[N][2],dp[N][2],head[N],a[N],b[N]; 13 void insert(int x,int y) 14 { 15 e[++cnt].to=y,e[cnt].from=head[x],head[x]=cnt; 16 e[++cnt].to=x,e[cnt].from=head[y],head[y]=cnt; 17 } 18 matrix mul(matrix a,matrix b) 19 { 20 matrix c; c.init(); 21 for (int i=0;i<2;i++) for (int j=0;j<2;j++) for (int k=0;k<2;k++) c.a[i][j]=max(c.a[i][j],a.a[i][k]+b.a[k][j]); 22 return c; 23 } 24 void dfs1(int x,int fa) 25 { 26 t[x].deep=t[fa].deep+1,t[x].size=1,t[x].fa=fa; 27 for (int i=head[x];i;i=e[i].from) if (e[i].to!=fa) 28 { 29 dfs1(e[i].to,x),t[x].size+=t[e[i].to].size; 30 if (t[e[i].to].size>t[t[x].son].size) t[x].son=e[i].to; 31 } 32 } 33 void dfs2(int x,int pre) 34 { 35 t[x].id=++tot,t[x].top=pre,b[tot]=x,t[pre].end=tot; 36 if (t[x].son) dfs2(t[x].son,pre); 37 for (int i=head[x];i;i=e[i].from) if (e[i].to!=t[x].fa&&e[i].to!=t[x].son) dfs2(e[i].to,e[i].to); 38 } 39 void dfs3(int x) 40 { 41 ldp[x][1]=a[x]; 42 for (int i=head[x];i;i=e[i].from) if (e[i].to!=t[x].fa&&e[i].to!=t[x].son) dfs3(e[i].to),ldp[x][0]+=max(dp[e[i].to][1],dp[e[i].to][0]),ldp[x][1]+=dp[e[i].to][0]; 43 dp[x][0]+=ldp[x][0],dp[x][1]+=ldp[x][1]; 44 if (!t[x].son) return; 45 dfs3(t[x].son),dp[x][0]+=max(dp[t[x].son][1],dp[t[x].son][0]),dp[x][1]+=dp[t[x].son][0]; 46 } 47 void build(int d,int l,int r) 48 { 49 if (l==r) { val[b[l]].a[0][0]=ldp[b[l]][0],val[b[l]].a[1][0]=ldp[b[l]][1],val[b[l]].a[0][1]=ldp[b[l]][0],val[b[l]].a[1][1]=-inf,T[d]=val[b[l]]; return; } 50 int mid=l+r>>1; 51 build(d*2,l,mid),build(d*2+1,mid+1,r),T[d]=mul(T[d*2],T[d*2+1]); 52 } 53 void updata(int d,int l,int r,int x) 54 { 55 if (l==r&&l==x) { T[d]=val[b[x]]; return; } 56 int mid=l+r>>1; 57 if (mid>=x) updata(d*2,l,mid,x); else updata(d*2+1,mid+1,r,x); 58 T[d]=mul(T[d*2],T[d*2+1]); 59 } 60 matrix query(int d,int l,int r,int L,int R) 61 { 62 if (l>=L&&r<=R) return T[d]; 63 int mid=l+r>>1; 64 if (mid>=R) return query(d*2,l,mid,L,R); 65 if (mid<L) return query(d*2+1,mid+1,r,L,R); 66 return mul(query(d*2,l,mid,L,R),query(d*2+1,mid+1,r,L,R)); 67 } 68 void change(int x,int y) 69 { 70 val[x].a[1][0]+=y-a[x],a[x]=y; 71 while (x!=0) 72 { 73 int now=t[x].top; 74 last=query(1,1,n,t[now].id,t[now].end),updata(1,1,n,t[x].id),front=query(1,1,n,t[now].id,t[now].end); 75 x=t[now].fa,val[x].a[0][0]+=max(front.a[0][0],front.a[1][0])-max(last.a[0][0],last.a[1][0]),val[x].a[0][1]=val[x].a[0][0],val[x].a[1][0]+=front.a[0][0]-last.a[0][0]; 76 } 77 } 78 int main() 79 { 80 freopen("data.in","r",stdin); 81 scanf("%d%d",&n,&m); 82 for (int i=1;i<=n;i++) scanf("%d",&a[i]); 83 for (int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),insert(x,y); 84 dfs1(1,0),dfs2(1,1),dfs3(1),build(1,1,n); 85 for (int i=1,x,y;i<=m;i++) scanf("%d%d",&x,&y),change(x,y),ans=query(1,1,n,t[1].id,t[1].end),printf("%d\n",max(ans.a[0][0],ans.a[1][0])); 86 }
标签:val,剖分,int,mid,son,ldp,动态,dp 来源: https://www.cnblogs.com/Comfortable/p/11365011.html