zoukankan      html  css  js  c++  java
  • 「刷题」保卫王国

      动态$dp$的板子题,然而我线性代数太菜写了好几个小时。

      由于我只会树剖的$log^2n$所以跑的也奇慢,不过在一通对拍下终于痛苦$AC$了。

      简单说一下$ddp$的思路。

      按树剖来说的话,就是分离重儿子和轻儿子在$dp$中的贡献,在数据结构中记录非重儿子的信息。

      这样由于我们修改一个点的权值,必然会改变他父链上的点的$dp$值,我们发现这个点作为重儿子的情况下是不需要修改任何信息的,需要修改的仅仅是作为轻儿子的请况,我们发现这样的轻边是$logn$级别的。同时对于父链一条轻边的起点,这个点必然是属于他所属重链的重儿子,那么这条重链非链尾(这个点)的部分均不需要修改,这样修改的次数就是$logn$条的,数据结构维护即可。

      首先考虑这道题的$O(nm)dp$。

      设$dp[x][0/1]$为点$x$选/不选的情况下,子树的点全部被覆盖的最小代价。

      那么有转移:$$dp[x][s]=egin{cases}&sumlimits_{tin son(x)}dp[t][!s] s=0&\&a[x]+sumlimits_{tin son(x)}min{dp[t][s],dp[t][!s]} s=1&end{cases}$$

      这样每次一修改我们就重复这一过程,复杂度就是$O(nm)$的了。

      考虑复杂度瓶颈。

      在于$dp$必须要重复计算每个位置的值,而有很多是没有被修改影响的。

      我们考虑一下一个算法,对于修改的点,发现受他影响的只有他父链上的点,那么可以只做父链上的点的$dp$。

      然而轻松被链式数据卡成$nm$。

      思考一下能不能用数据结构维护这个$dp$。显然不能,这个$dp$暂时不具有结合律。

      尝试线性代数优化,结合树剖也许有不一样的效果。

      拿出矩阵来。

      首先设一个参量$g[x][0/1]$,$ch[x]$为一个节点的重儿子。

      定义:$$g[x][s]=egin{cases}&sumlimits_{tin son(x),t!=ch[x]}dp[t][!s] s=0&\&a[x]+sumlimits_{tin son(x),t!=ch[x]}min{dp[t][s],dp[t][!s]} s=1&end{cases}$$

      维护一个矩阵:$$R[x]=left[egin{array}{c}infty &g[x][0]\g[x][1]&g[x][1]end{array} ight]$$

      维护一个矩阵:$$G[x]=left[egin{array}{c}dp[x][0]\dp[x][1]end{array} ight]$$

      定义一种矩阵运算:$$A=B*C <=> a_{i,j}=minlimits_{k}{b_{i,k}+c_{k,j}}$$

      定义单位元:$$I=left[egin{array}{c}0&infty\ infty&0end{array} ight]$$

      好,那么根据这种运算我们知道:$$R[x]G[ch[x]]=G[x]$$

      这样可以分离重儿子的贡献,并且$dp$的转移也做到了有结合律,可以用数据结构了。

      线段树维护重链来做到这一点。

      那么对于每一个修改的点,考虑这个点对其轻父链的影响,首先计算出当前点所在重链的矩阵乘积,这个矩阵乘积的后一列就是当前重链顶的$dp$值,这样计算修改前后的差值,这样可以快速的修改轻父链,做到总复杂度$O(nlog^2n)$

  • 相关阅读:
    4_url_for的使用
    3_Flask中URL与视图函数的映射
    2_Fiask的配置文件config
    C10K问题渣翻译
    (转载)Linux 套接字编程中的 5 个隐患
    linux2.6.24内核源代码分析(2)——扒一扒网络数据包在链路层的流向路径之一
    linux2.6.24内核源代码分析(1)——扒一扒sk_buff
    andriod手机签到应用服务器设计
    (转)ubuntu安装opengl
    线段树
  • 原文地址:https://www.cnblogs.com/Lrefrain/p/11838626.html
Copyright © 2011-2022 走看看