[题目链接] https://www.luogu.org/problemnew/show/P4719

题解(shadowice)

代码借鉴

求最大独立集是一个经典的问题,这个转移如果套上树剖就可以转化为序列上的问题,就可以用所谓的矩阵乘法维护了.

设\(g[x][0/1]\)代表重儿子以外的答案,\(f[x][0/1]\)代表最终的答案,假如维护好了这两个信息,那么重链上的转移就是正确的了.

注意矩阵乘法的顺序,手模可以发现答案是重链上从上到下的g[]相乘再乘上最下面的点的\(f[]\).而最底下的点的\(f[]\)恰好就是\(g[]\),而乘的过程中只要满足\(g[]\)的\(a[0][0]\)和\(a[1][0]\)正确就行了,所以最终答案就可以直接是\(rt\)所在的重链的矩阵乘起来.

dp用矩阵乘法维护可以参考这道题 .取max操作也可以用矩阵维护.

具体实现:修改某一个点权值就把它的信息更改,直接更新它所在的重链的答案,再一路更新上面所有的重链.

注意几点:

\(1.\)证明正确性的时候,一定要把矩阵乘法的顺序手模出来,一般要转化为与树剖的dfn序相符.

\(2.\)初始的答案在建树时存进去,所以还要先一遍dfs算出最初的答案.

细节详见代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL INF=1e18+7;
inline LL read(){register LL x=0,f=1;register char c=getchar();while(c<48||c>57){if(c=='-')f=-1;c=getchar();}while(c>=48&&c<=57)x=(x<<3)+(x<<1)+(c&15),c=getchar();return f*x;
}const int MAXN=100005;
const int MAXM=200005;struct Edge{int v,next;
}e[MAXM];
int first[MAXN],Ecnt=0;
inline void Add_edge(int u,int v){e[++Ecnt]=(Edge){v,first[u]};first[u]=Ecnt;
}int size[MAXN],top[MAXN],seg[MAXN],rev[MAXN],son[MAXN],fa[MAXN],bot[MAXN],val[MAXN];
LL f[MAXN][2];
int n,m;inline void dfs1(int u,int pre){size[u]=1;for(int i=first[u];i;i=e[i].next){int v=e[i].v;if(v==pre) continue;fa[v]=u;dfs1(v,u);size[u]+=size[v];if(size[v]>size[son[u]]) son[u]=v;}
}inline void dfs2(int u,int pre){seg[u]=++seg[0];rev[seg[0]]=u;if(son[u]){top[son[u]]=top[u];dfs2(son[u],u);bot[u]=bot[son[u]];//bot[]的更新}else bot[u]=u;for(int i=first[u];i;i=e[i].next){int v=e[i].v;if(v==pre||v==son[u]) continue; top[v]=v;dfs2(v,u);      }
}inline void dfs3(int u,int pre){f[u][1]=val[u];for(int i=first[u];i;i=e[i].next){int v=e[i].v;if(v==pre) continue;dfs3(v,u);f[u][1]+=f[v][0];f[u][0]+=max(f[v][0],f[v][1]);//算出初始答案}
}struct Matrix{LL a[2][2];//这题矩阵乘法可以直接这么写inline friend Matrix operator * (Matrix a,Matrix b){Matrix res;res.a[0][0]=max(a.a[0][0]+b.a[0][0],a.a[0][1]+b.a[1][0]);res.a[0][1]=max(a.a[0][0]+b.a[0][1],a.a[0][1]+b.a[1][1]);res.a[1][0]=max(a.a[1][0]+b.a[0][0],a.a[1][1]+b.a[1][0]);res.a[1][1]=max(a.a[1][0]+b.a[0][1],a.a[1][1]+b.a[1][1]);return res;}
}g[MAXN<<2],tmp[MAXN];struct SGT{
#define ls (rt<<1)
#define rs (rt<<1|1)inline void pushup(int rt){g[rt]=g[ls]*g[rs];}inline void build(int rt,int l,int r){if(l==r){int u=rev[l],g0=0,g1=val[u];for(int i=first[u];i;i=e[i].next){int v=e[i].v;if(v==son[u]||v==fa[u]) continue;g0+=max(f[v][0],f[v][1]);g1+=f[v][0];}tmp[l]=g[rt]=(Matrix){g0,g0,g1,-INF};//建树时就要算出初始的答案!!!return;}int mid=(l+r)>>1;build(ls,l,mid);build(rs,mid+1,r);pushup(rt);}inline Matrix query(int rt,int l,int r,int x,int y){if(l>=x&&r<=y) return g[rt];int mid=(l+r)>>1;if(y<=mid) return query(ls,l,mid,x,y);if(mid<x) return query(rs,mid+1,r,x,y);return query(ls,l,mid,x,y)*query(rs,mid+1,r,x,y);}inline Matrix GetMat(int u){return query(1,1,n,seg[top[u]],seg[bot[u]]);}inline void modify(int rt,int l,int r,int p){if(l==r&&l==p){g[rt]=tmp[l];return;}int mid=(l+r)>>1;if(p<=mid) modify(ls,l,mid,p);else modify(rs,mid+1,r,p);pushup(rt);}inline void modify(int u,int w){tmp[seg[u]].a[1][0]+=w-val[u],val[u]=w;//细节处理,先更新再说while(u){Matrix a=GetMat(u);modify(1,1,n,seg[u]);//算出u所在的重链的答案Matrix b=GetMat(u);u=fa[top[u]];//一路更新上去.if(!u) break;//利用更新前后的差值去更新fa//tmp是一个中间变量,方便更新g[]tmp[seg[u]].a[0][1]=(tmp[seg[u]].a[0][0]+=max(b.a[0][0],b.a[1][0])-max(a.a[0][0],a.a[1][0]));tmp[seg[u]].a[1][0]+=b.a[0][0]-a.a[0][0];}}
#undef ls
#undef rs
}T;int main(){
//  freopen("asd.in","r",stdin);n=read(),m=read();for(int i=1;i<=n;i++)val[i]=read();for(int i=1;i<=n-1;i++){int x=read(),y=read();Add_edge(x,y);Add_edge(y,x);//记得建双向边}dfs1(1,0);top[1]=1;dfs2(1,0);dfs3(1,0);T.build(1,1,n);for(int i=1;i<=m;i++){int x=read(),y=read();T.modify(x,y);Matrix ans=T.GetMat(1);//答案就转化为所有的g[]乘起来printf("%lld\n",max(ans.a[0][0],ans.a[1][0]));}
}

转载于:https://www.cnblogs.com/lizehon/p/10428349.html

P4719 【模板】动态dp相关推荐

  1. 【洛谷P4719】动态DP【LCT】【矩阵】

    之前的后缀平衡树其实没完,只是过于鬼畜就弃了 传送门 题意:带修改点权的最大独立集 N≤1e5N \leq 1e5N≤1e5 一个没啥用的模板,不过适合练习LCT 先写出方程 f(u,0)=∑v∈so ...

  2. P4719 【模板】“动态 DP“动态树分治(矩阵/轻重链剖分/ddp)

    P4719 [模板]"动态 DP"&动态树分治 求解树上最大权独立集,但是需要支持修改. https://www.luogu.com.cn/problem/solution ...

  3. 全局平衡二叉树 P4751 【模板】“动态DP“

    全局平衡二叉树 P4751 [模板]"动态DP" P4751 [模板]"动态DP"&动态树分治(加强版) 有事没事就用 v e c t o r \tt ...

  4. 【洛谷】P4643 【模板】动态dp

    题解 在冬令营上听到冬眠的东西,现在都是板子了猫锟真的是好毒瘤啊(雾) (立个flag,我去thusc之前要把WC2018T1乱搞过去= =) 好的,我们可以参考猫锟的动态动态dp的课件,然后你发现你 ...

  5. [总结] 动态DP学习笔记

    学习了一下动态DP 问题的来源: 给定一棵 \(n\) 个节点的树,点有点权,有 \(m\) 次修改单点点权的操作,回答每次操作之后的最大带权独立集大小. 首先一个显然的 \(O(nm)\) 的做法就 ...

  6. P5024-保卫王国【动态dp,最小覆盖集】

    正题 题目链接:https://www.luogu.org/problem/P5024 题目大意 一棵树,每次有要求 axby:a\ x\ b\ y:a x b y:表示aaa点是否必选和bbb点是否 ...

  7. [动态dp]线段树维护转移矩阵

    背景:czy上课讲了新知识,从未见到过,总结一下. 所谓动态dp,是在动态规划的基础上,需要维护一些修改操作的算法. 这类题目分为如下三个步骤:(都是对于常系数齐次递推问题) 1先不考虑修改,不考虑区 ...

  8. uoj#268. 【清华集训2016】数据交互(动态dp+堆)

    传送门 动态dp我好像还真没咋做过--通过一个上午的努力光荣的获得了所有AC的人里面的倒数rk3 首先有一个我一点也不觉得显然的定理,如果两条路径相交,那么一定有一条路径的\(LCA\)在另一条路径上 ...

  9. luogu5024 [NOIp2018]保卫王国 (动态dp)

    可以直接套动态dp,但因为它询问之间相互独立,所以可以直接倍增记x转移到fa[x]的矩阵 1 #include<bits/stdc++.h> 2 #define CLR(a,x) mems ...

  10. 回文串 --- 动态dp UVA 11584

    题目链接: https://cn.vjudge.net/problem/34398/origin 本题的大意其实很简单,就是找回文串,大致的思路如下: 1. 确定一个回文串,这里用到了自定义的chec ...

最新文章

  1. ZigZag 与 反ZigZag编码
  2. 【Android 进程保活】应用进程拉活 ( 双进程守护 + JobScheduler 保活 | 成功率最高 | 推荐使用 )
  3. 【Android】窗口构成 应用窗口+系统窗口
  4. 完成AOP 顶层设计-AopConfig
  5. Redux-学习笔记
  6. CodeCraft-20 (Div. 2) D. Nash Matrix 构造 + dfs
  7. DP问题之 捞鱼问题
  8. vue 上次登录时间_vue实现登录之后长时间未操作,退出登录
  9. 无意中发现Markdown,最终解放了我
  10. python 内存溢出能捕获吗_python之记录一次内存溢出
  11. atitit 项目管理 持续集成 构建管理CI jenkins.docx
  12. win7 蓝牙4.0 ble驱动_Android FrameWorkamp;HAL视频最新进度: 蓝牙更新6节(更新时间2019年3月27日)...
  13. NameError: name ‘xxx‘ is not defined问题总结
  14. 选择排序之简单选择排序
  15. npoi导出文件不保存在服务器,winform NPOI excel 导出并选择保存文件路径
  16. 现实中的项目范围变更
  17. 你听说过FOC吗?FOC的原理是什么?
  18. oracle 存储过程误删,Oracle中怎么恢复被删掉的存储过程
  19. 用python将txt文件中的内容导入到excel文件中
  20. 安装python2.7安装方法_python2.7环境如何安装

热门文章

  1. Swift实现CoreData存储数据
  2. winSockets编程(二)socket函数
  3. 磁盘阵列简介---图片说明
  4. token验证_Swagger中添加Token验证
  5. Java的知识点30——线程的优先级、终止线程的典型方式、获取线程基本信息的方法
  6. matlab的知识点1
  7. 用JavaScript实现简单的excel列转sql字符串
  8. jquery的checked以及disabled
  9. python 技术篇-使用logging日志模块自定义时间格式
  10. Python 技术篇 - 查看python库都包含什么方法,查看python模块某个方法的具体用法源码,查看python模块所在的物理位置,查看python库都包含哪些属性