方法二:LCT+矩阵乘法
上文中,我们用线段树来维护重链上的各种矩阵转移.
第二种方法是将树链剖分替换为动态树.
我们知道,矩阵乘法 $\begin{bmatrix} F_{u,0} & F_{u,0}\\ F_{u,1}  & -\infty \end{bmatrix}\times\begin{bmatrix} F_{i,0}\\F_{i,1} \end{bmatrix}=\begin{bmatrix} F_{u,0}\\F_{u,1} \end{bmatrix}$ 中第一个矩阵中的每一个 $F_{u,k}$ 都是指考虑轻链时 $u$ 的 DP 值.
在 $LCT$ 中,树的轻重路径是交替变换的.
我们用维护子树信息的方式维护即可.
即设 $tmp$ 矩阵表示该点虚儿子的所有 DP 值的贡献(只是不包括重儿子).
再设 $t$ 矩阵维护 $Splay$ 中的转移.
具体细节看看代码:
 

Code:

  1. // luogu-judger-enable-o2
  2. //Dynamic DP with LCT
  3. #include<bits/stdc++.h>
  4. #define ll long long
  5. #define setIO(s) freopen(s".in","r",stdin)
  6. #define maxn 100002
  7. #define inf 100000000
  8. using namespace std;
  9. //Link cut tree
  10. void de()
  11. {
  12. printf("ok\n");
  13. }
  14. namespace LCT
  15. {
  16.  
  17. struct Matrix
  18. {
  19. ll a[2][2];
  20. ll*operator[](int x){ return a[x];}
  21. }t[maxn],tmp[maxn];
  22. Matrix operator*(Matrix a,Matrix b)
  23. {
  24. Matrix c;
  25. c[0][0]=max(a[0][0]+b[0][0],a[0][1]+b[1][0]);
  26. c[0][1]=max(a[0][0]+b[0][1],a[0][1]+b[1][1]);
  27. c[1][0]=max(a[1][0]+b[0][0],a[1][1]+b[1][0]);
  28. c[1][1]=max(a[1][0]+b[0][1],a[1][1]+b[1][1]);
  29. return c;
  30. }
  31.  
  32. //tmp :: 虚儿子信息
  33. //t :: 树剖实际转移矩阵
  34. #define lson ch[x][0]
  35. #define rson ch[x][1]
  36. int ch[maxn][2],f[maxn];
  37. int isRoot(int x)
  38. {
  39. return !(ch[f[x]][0]==x || ch[f[x]][1]==x);
  40. }
  41. int get(int x)
  42. {
  43. return ch[f[x]][1]==x;
  44. }
  45. void pushup(int x)
  46. {
  47. t[x]=tmp[x];
  48. if(lson) t[x]=t[lson]*t[x];
  49. if(rson) t[x]=t[x]*t[rson];
  50. }
  51. void rotate(int x)
  52. {
  53. int old=f[x],fold=f[old],which=get(x);
  54. if(!isRoot(old)) ch[fold][ch[fold][1]==old]=x;
  55. ch[old][which]=ch[x][which^1],f[ch[old][which]]=old;
  56. ch[x][which^1]=old,f[old]=x,f[x]=fold;
  57. pushup(old),pushup(x);
  58. }
  59. void splay(int x)
  60. {
  61. int u=x;
  62. while(!isRoot(u)) u=f[u];
  63. u=f[u];
  64. for(int fa;(fa=f[x])!=u;rotate(x))
  65. if(f[fa]!=u) rotate(get(fa)==get(x)?fa:x);
  66. }
  67. void Access(int x)
  68. {
  69. for(int y=0;x;y=x,x=f[x])
  70. {
  71. splay(x);
  72. if(rson)
  73. {
  74. tmp[x][0][0]+=max(t[rson][0][0],t[rson][1][0]);
  75. tmp[x][1][0]+=t[rson][0][0];
  76. }
  77. if(y)
  78. {
  79. tmp[x][0][0]-=max(t[y][0][0],t[y][1][0]);
  80. tmp[x][1][0]-=t[y][0][0];
  81. }
  82. tmp[x][0][1]=tmp[x][0][0];
  83. rson=y,pushup(x);
  84. }
  85. }
  86. };
  87.  
  88. //variables
  89. int DP[maxn][2];
  90. int V[maxn],hd[maxn],to[maxn<<1],nex[maxn<<1];
  91. int n,Q,edges;
  92. void add(int u,int v){ nex[++edges]=hd[u],hd[u]=edges,to[edges]=v; }
  93.  
  94. //build graph
  95. void dfs(int u,int ff)
  96. {
  97. LCT::f[u]=ff;
  98. DP[u][0]=0;
  99. DP[u][1]=V[u];
  100. for(int i=hd[u];i;i=nex[i])
  101. {
  102. int v=to[i];
  103. if(v==ff) continue;
  104. dfs(v,u);
  105. DP[u][0]+=max(DP[v][1],DP[v][0]);
  106. DP[u][1]+=DP[v][0];
  107. }
  108. LCT::tmp[u]=(LCT::Matrix){ DP[u][0], DP[u][0], DP[u][1], -inf};
  109. LCT::t[u]=LCT::tmp[u];
  110. }
  111.  
  112. //主程序~
  113. int main()
  114. {
  115. // setIO("input");
  116. scanf("%d%d",&n,&Q);
  117. for(int i=1;i<=n;++i) scanf("%d",&V[i]);
  118. for(int i=1,u,v;i<n;++i)
  119. {
  120. scanf("%d%d",&u,&v);
  121. add(u,v),add(v,u);
  122. }
  123. dfs(1,0);
  124. while(Q--)
  125. {
  126. int x,y;
  127. scanf("%d%d",&x,&y);
  128. LCT::Access(x);
  129. LCT::splay(x);
  130. LCT::tmp[x][1][0]+=(ll)y-V[x];
  131. V[x]=y;
  132. LCT::pushup(x);
  133. LCT::splay(1);
  134. printf("%lld\n",max(LCT::t[1][0][0], LCT::t[1][1][0]));
  135. }
  136. return 0;
  137. }

  

luogu P4719 【模板】动态 DP 矩阵乘法 + LCT的更多相关文章

  1. Luogu P4643 【模板】动态dp(矩阵乘法,线段树,树链剖分)

    题面 给定一棵 \(n\) 个点的树,点带点权. 有 \(m\) 次操作,每次操作给定 \(x,y\) ,表示修改点 \(x\) 的权值为 \(y\) . 你需要在每次操作之后求出这棵树的最大权独立集 ...

  2. [luogu 4719][模板]动态dp

    传送门 Solution \(f_{i,0}\) 表示以i节点为根的子树内,不选i号节点的最大独立集 \(f_{i,1}\)表示以i节点为根的子树内,选i号节点的最大独立集 \(g_{i,0}\) 表 ...

  3. 【bzoj2004】[Hnoi2010]Bus 公交线路 状压dp+矩阵乘法

    题目描述 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距离均为1km. 作为公交车线路的规划者,小Z调查了市民的需求,决定按下述规则设计 ...

  4. 【bzoj3329】Xorequ 数位dp+矩阵乘法

    题目描述 输入 第一行一个正整数,表示数据组数据 ,接下来T行每行一个正整数N 输出 2*T行第2*i-1行表示第i个数据中问题一的解, 第2*i行表示第i个数据中问题二的解, 样例输入 1 1 样例 ...

  5. [模板] 动态dp

    用途 对于某些树形dp(目前只会树上最大权独立集或者类似的),动态地修改点权,并询问修改后的dp值 做法(树剖版) 以最大权独立集为例 设$f[x][0/1]$表示x选不选,这棵子树的最大权独立集大小 ...

  6. 【BZOJ-4386】Wycieczki DP + 矩阵乘法

    4386: [POI2015]Wycieczki Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 197  Solved: 49[Submit][Sta ...

  7. [模板][题解][Luogu1939]矩阵乘法加速递推(详解)

    题目传送门 题目大意:计算数列a的第n项,其中: \[a[1] = a[2] = a[3] = 1\] \[a[i] = a[i-3] + a[i - 1]\] \[(n ≤ 2 \times 10^ ...

  8. LOJ.6074.[2017山东一轮集训Day6]子序列(DP 矩阵乘法)

    题目链接 参考yww的题解.本来不想写来但是他有一些笔误...而且有些地方不太一样就写篇好了. 不知不觉怎么写了这么多... 另外还是有莫队做法的...(虽然可能卡不过) \(60\)分的\(O(n^ ...

  9. ZOJ - 3216:Compositions (DP&矩阵乘法&快速幂)

    We consider problems concerning the number of ways in which a number can be written as a sum. If the ...

随机推荐

  1. 记一次ruby的安装

    1,下载rubyinstall 安装包及devkit包 登陆网站 :http://rubyinstaller.org/downloads/ 安装rubyinstall包时添加到环境变量 2,安装完in ...

  2. 【翻译自mos文章】在12c数据库中,哪种audit trail 受到支持?

    在12c数据库中,哪种audit trail 受到支持? 来源于:What Audit Trail Types Are Supported For A 12c Database? (文档 ID 198 ...

  3. LeetCode之LCP(Longest Common Prefix)问题

    这个也是简单题目.可是关键在于题意的理解. 题目原文就一句话:Write a function to find the longest common prefix string amongst an ...

  4. ActionBar第一课简单介绍

    .ActionBar简单介绍 ActionBar是显示在界面顶部的标题栏. 官方推荐开发者尽量使用 ActionBar代替OptionsMenu和TabHost. 典型应用方式有: 使用导航栏中的应用 ...

  5. hook 鼠标键盘消息实例分析

    1.木马控制及通信方法包含:双管道,port重用.反弹技术.Hook技术,今天重点引用介绍一下hook的使用方法,hook信息后能够将结果发送到hacker邮箱等.实现攻击的目的. 转自:http:/ ...

  6. hihocoder 1680 hiho字符串2 dp求方案数+递归

    我们定义第一代hiho字符串是"hiho". 第N代hiho字符串是由第N-1代hiho字符串变化得到,规则是: h -> hio i -> hi o -> ho ...

  7. B1391 [Ceoi2008]order 最大权闭合图 最小割

    啊啊啊,假的题吧!!!我用的当前弧优化T了6个点,其他人不用优化AC!!!震惊!!!当前弧优化是假的吧!!! 到现在我也没调出来...大家帮我看看为啥70.... 来讲一下这个题的思路,就是设一个源点 ...

  8. Java-java-com-util-common-service:TreeService.java

    ylbtech-Java-java-com-util-common-service:TreeService.java 1.返回顶部 1. package com.shineyoo.manager.ut ...

  9. go之结构体

    一.关于结构体 简述 1.go 语言的切片可以存储同一类型的数据,但是结构体可以为不同项定义不同的数据类型 2.结构体是有一系列具有相同类型或不同类型的数据构成的数据集合 3.因为go 没有类似于类的 ...

  10. 2-bitmap

    在2.5亿个整数中找出不重复的整数,注,内存不足以容纳这2.5亿个整数. 思路: bitmap用一个bit来代表存在还是不存在,现在我们要判断重不重复,则需要三个状态:不存在,存在一个,存在多个.2b ...