前言

其实我只是为了过掉模板而写的ddp,实际应用被吊着锤

Solution

并不想写详细的过程

一句话过程:将子树中轻儿子的贡献挂到这个点上面来

详细版:(引用yyb)

总结一下的话,大致的过程是这样子的:首先我们考虑我们的转移方程,发现能够将其改写为矩乘的形式,那么我们首先将转移改为矩乘。我们把轻链和重链的转移分开考虑。这样子想,我们的重链被我们单独拎了出来,每个重链上都挂上了若干轻儿子,显然轻儿子对于重链上的独立集的选择是没有影响的,换而言之,如果轻儿子的贡献考虑完之后,那么等价于链上每个点选或者不选有一个权值,求最大独立集。而对于链上的这个东西,是可以直接用线段数维护矩阵支持修改和查询的,那么这题就只需要这么做就好了。即只修改这个点到达根节点上的所有轻链对于父亲的贡献,对于重儿子的贡献先暂时不考虑,每次线段树查询矩阵乘积即可求解出每个点的矩阵,就可以快速求解答案了

代码实现

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<string.h>
  4. #include<math.h>
  5. #include<algorithm>
  6. #include<queue>
  7. #include<set>
  8. #include<map>
  9. #include<iostream>
  10. using namespace std;
  11. #define ll long long
  12. #define re register
  13. #define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
  14. inline int gi(){
  15. int f=1,sum=0;char ch=getchar();
  16. while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
  17. while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
  18. return f*sum;
  19. }
  20. const int N=100010;
  21. const ll Inf=1e18+10;
  22. int a[N],front[N],nxt[N<<1],to[N<<1],cnt,n,m,dep[N],son[N],siz[N],fa[N],top[N],dfn[N],Time,id[N],bot[N];
  23. void Add(int u,int v){
  24. to[++cnt]=v;nxt[cnt]=front[u];front[u]=cnt;
  25. }
  26. struct matrix{
  27. ll a[2][2];
  28. ll*operator [](int x){return a[x];};
  29. matrix operator*(matrix b)const{
  30. matrix c;
  31. for(int i=0;i<2;i++)
  32. for(int j=0;j<2;j++){
  33. c[i][j]=0;
  34. for(int k=0;k<2;k++)
  35. c[i][j]=max(c[i][j],a[i][k]+b[k][j]);
  36. }
  37. return c;
  38. }
  39. }t[N<<2],tmp[N];
  40. void dfs1(int u,int f){
  41. dep[u]=dep[f]+1;siz[u]=1;fa[u]=f;
  42. for(int i=front[u];i;i=nxt[i]){
  43. int v=to[i];
  44. if(v==f)continue;
  45. dfs1(v,u);
  46. siz[u]+=siz[v];if(siz[v]>siz[son[u]])son[u]=v;
  47. }
  48. }
  49. void dfs2(int u,int tp){
  50. top[u]=tp;dfn[u]=++Time;id[Time]=u;
  51. if(son[u]){dfs2(son[u],tp),bot[u]=bot[son[u]];}
  52. else bot[u]=u;
  53. for(int i=front[u];i;i=nxt[i]){
  54. int v=to[i];
  55. if(v==fa[u] || v==son[u])continue;
  56. dfs2(v,v);
  57. }
  58. }
  59. ll f[N][2];
  60. void dp(int u){
  61. f[u][1]=a[u];
  62. for(int i=front[u];i;i=nxt[i]){
  63. int v=to[i];
  64. if(v==fa[u])continue;
  65. dp(v);
  66. f[u][0]+=max(f[v][1],f[v][0]);
  67. f[u][1]+=f[v][0];
  68. }
  69. }
  70. void build(int o,int l,int r){
  71. if(l==r){
  72. int u=id[l];int g0=0,g1=a[u];
  73. for(int i=front[u];i;i=nxt[i]){
  74. int v=to[i];
  75. if(v==fa[u] || v==son[u])continue;
  76. g0+=max(f[v][1],f[v][0]);g1+=f[v][0];
  77. }
  78. tmp[l]=t[o]=(matrix){g0,g0,g1,-Inf};
  79. return;
  80. }
  81. int mid=(l+r)>>1;
  82. build(o<<1,l,mid);build(o<<1|1,mid+1,r);
  83. t[o]=t[o<<1]*t[o<<1|1];
  84. }
  85. //------------以上是dp+树剖-----------------------------------------------
  86. void Modify(int o,int l,int r,int p){
  87. if(l==r){t[o]=tmp[l];return;}
  88. int mid=(l+r)>>1;
  89. if(p<=mid)Modify(o<<1,l,mid,p);
  90. else Modify(o<<1|1,mid+1,r,p);
  91. t[o]=t[o<<1]*t[o<<1|1];
  92. }
  93. matrix query(int o,int l,int r,int posl,int posr){
  94. if(posl==l && posr==r)return t[o];
  95. int mid=(l+r)>>1;
  96. if(mid>=posr)return query(o<<1,l,mid,posl,posr);
  97. else if(mid<posl)return query(o<<1|1,mid+1,r,posl,posr);
  98. return query(o<<1,l,mid,posl,mid)*query(o<<1|1,mid+1,r,mid+1,posr);
  99. }
  100. matrix ask(int x){return query(1,1,n,dfn[top[x]],dfn[bot[x]]);}
  101. void Modify(int u,int w){
  102. tmp[dfn[u]][1][0]+=w-a[u];a[u]=w;
  103. while(u){
  104. matrix a=ask(top[u]);Modify(1,1,n,dfn[u]);
  105. matrix b=ask(top[u]);
  106. u=fa[top[u]];if(!u)break;
  107. tmp[dfn[u]][0][1]=(tmp[dfn[u]][0][0]+=max(b[0][0],b[1][0])-max(a[0][0],a[1][0]));
  108. tmp[dfn[u]][1][0]+=b[0][0]-a[0][0];
  109. }
  110. }
  111. int main(){
  112. n=gi();m=gi();
  113. for(int i=1;i<=n;i++)a[i]=gi();
  114. for(int i=1;i<n;i++){int u=gi(),v=gi();Add(u,v);Add(v,u);}
  115. dfs1(1,0);dfs2(1,1);dp(1);build(1,1,n);
  116. matrix t;
  117. while(m--){
  118. int u=gi(),x=gi();
  119. Modify(u,x);
  120. t=ask(1);
  121. printf("%lld\n",max(t[0][0],t[1][0]));
  122. }
  123. return 0;
  124. }

【洛谷4719】 动态dp(树链剖分,dp,矩阵乘法)的更多相关文章

  1. 洛谷P3313 [SDOI2014]旅行(树链剖分 动态开节点线段树)

    题意 题目链接 Sol 树链剖分板子 + 动态开节点线段树板子 #include<bits/stdc++.h> #define Pair pair<int, int> #def ...

  2. BZOJ2243 洛谷2486 [SDOI2011]染色 树链剖分

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2243 题目传送门 - 洛谷2486 题意概括 一棵树,共n个节点. 让你支持以下两种操作,共m次操 ...

  3. 洛谷P3459 [POI2007]MEG-Megalopolis [树链剖分]

    题目传送门 MEG 题目描述 Byteotia has been eventually touched by globalisation, and so has Byteasar the Postma ...

  4. 洛谷 P3950 部落冲突 树链剖分

    目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例1 输出样例1 输入样例2 输出样例2 输入样例3 输出样例3 说明 思路 AC代码 总结 题面 题目链接 P3 ...

  5. 洛谷 P2486 [SDOI2011]染色 树链剖分

    目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 思路 PushDown与Update Q AC代码 总结与拓展 题面 题目链接 P2486 ...

  6. 洛谷 P4211 [LNOI2014]LCA (树链剖分+离线)

    题目:https://www.luogu.org/problemnew/solution/P4211 相当难的一道题,其思想难以用言语表达透彻. 对于每个查询,区间[L,R]中的每个点与z的lca肯定 ...

  7. 洛谷P3038 牧草种植 [树链剖分]

    题目传送门 牧草种植 题目描述 Farmer John has N barren pastures (2 <= N <= 100,000) connected by N-1 bidirec ...

  8. 洛谷P4114 Qtree1(树链剖分+线段树)

    传送门 LCT秒天秒地用什么树剖 这题可以算是树剖的比较裸的题目了 把每一条边的权值下放到他两边的点中深度较深的那个 然后直接用树剖+线段树带进去乱搞就可以了 //minamoto #include& ...

  9. 洛谷$P4211\ [LNOI2014]\ LCA$ 树链剖分+线段树

    正解:树剖+线段树 解题报告: 传送门$QwQ$ 看到$dep[lca]$啥的就想到之前托腮腮$CSP$模拟$D1T3$的那个套路,,, 然后试下这个想法,于是$dep[lca(x,y)]=\sum_ ...

  10. 6.3 省选模拟赛 Decompose 动态dp 树链剖分 set

    LINK:Decompose 看起来很难 实际上也很难 考验选手的dp 树链剖分 矩阵乘法的能力. 容易列出dp方程 暴力dp 期望得分28. 对于链的情况 容易发现dp方程可以转矩阵乘法 然后利用线 ...

随机推荐

  1. C#.net随机数函数

    (1)Random rnd = new Random(); int rndNum = rnd.Next();           //int 取值范围内的随机数 int rndNum = rnd.Ne ...

  2. js td innerHTML

    用value不好使,用innerHTML可以.JS:document.getElementById("aa").innerHTML="单元格"; body:&l ...

  3. 理解数据结构Priority Queue

    我们知道Queue是遵循先进先出(First-In-First-Out)模式的,但有些时候需要在Queue中基于优先级处理对象.举个例子,比方说我们有一个每日交易时段生成股票报告的应用程序,需要处理大 ...

  4. 屏幕录像专家exe视频批量翻录成视频avi格式

    笔者下载过一些视频,全部是屏幕录像专家录制的exe视频,这些视频没有密码,可以顺利打开看看. 有一日想把这些视频转换成wmv格式放到手机上查看.一个目录下有那么大exe视频.一个个转特别麻烦. 后来想 ...

  5. c#/vb调用c编写的标准dll

    准备: 首先打开vc++ 6.0新建工程,选择Win32 Dynamic Link-Library,命名为stdLibrary 新建library.cpp文件,内容如下 #include <st ...

  6. PAT 1084 外观数列(20)(代码+思路+推荐测试用例)

    1084 外观数列(20 分) 外观数列是指具有以下特点的整数序列: d, d1, d111, d113, d11231, d112213111, ... 它从不等于 1 的数字 d 开始,序列的第 ...

  7. geoserver 通过代码实现发布地图服务

    GeoServer:代码实现批量发布地图服务 利用GeoServer发布WCS服务,那么如果我有很多数据需要进行发布,这样利用GeoServer提供的UI界面进行操作显然很不显示.那能不能利用GeoS ...

  8. [VBScript] 自动删除2小时以前生成的文件

    保存为deleteTempFiles.vbs,双击即可运行 dim folder, file, mFSO, subfolder Set mFSO = CreateObject("Script ...

  9. boosting_bagging

    boosting(提升法) 对于训练集中的每个样本建立全职W(i),当某个样本被错误分类概率很高时,样本的权重加大: 在迭代过程中,每一个迭代器都是一个弱分类器,我们需要用某种策略将其组合,作为最终模 ...

  10. 2018.07.20 bzoj2152: 聪聪可可(点分治)

    传送门 本蒟蒻AC的第二道点分治,调了30min" role="presentation" style="position: relative;"&g ...