首页 > 其他分享 >结合律优化

结合律优化

时间:2023-01-30 20:00:10浏览次数:50  
标签:... max 矩阵 DP 结合律 优化 转移 dp

概述

  • 结合律优化通过将冗长的转移用结合律压缩,高效实现...取某一段的 dp 结果?也可以带修。

实现原理

  • 首先,对应 DP 要满足结合律,即各部分转移的形式相互独立。典型的反例譬如求可行性的背包问题。

  • 然后上线段树。视情况不同,可能是基于矩阵的 DDP 或纯粹靠复杂线段树的...线段树优化 DP?另外还有全局平衡二叉树和 LCT 实现,但我都不会。

  • 如果不带修,也可以使用倍增实现。

例题

从最大子段和讲起

  • 题意:求 \(a_n\) 的最大子段和,带 \(m\) 次单点修改。

  • 数据范围:\(n,m\leqslant 10^5\)。应该也能 \(10^6\)?

  • 先谈谈静态意义下的朴素 dp。

    • 状态设计:\(dp_i\) 表示以 \(i\) 结尾的最大子段和。

    • 初始化:\(dp_0=0\)。

    • 转状态转移方程:\(dp_i=\max(dp_{i-1}+v_i,v_i)\)。

  • OK,这是一个很朴素的 \(O(n)\)。显然 \(O(nm)\) 不可接受,但我们看到它的转移条件基本互相不依赖,满足结合律。

  • 故首先考虑 DDP。考虑把每个转移都做成矩乘的形式:

    • 状态矩阵:\(\begin{bmatrix}dp_i & ans & 0\end{bmatrix}\)。特别地,一开始 \(ans=-inf\)。

    • 乘法法则:\(res_{i,j}=\max_{k=1}^m(A_{i,k}+B_{k,j})\)。显然,其满足结合律。

    • 转移矩阵:\(\begin{bmatrix}v_{i+1} & 0 & 0 \\ -inf & 0 & 0 \\ v_{i+1}& -inf &0\end{bmatrix}\)。

    • 解释一下,这里希望令 \(ans=max(ans,dp_i)\),这样真正的答案 \(Ans=\max(ans,res_1)\),\(res\) 是最后的答案矩阵。

    • 为什么求这个 \(ans\),而不是利用线段树对 \(dp_i\) 求 \(\max\)?嗯...DDP 的 sgt 的功能是把转移矩阵结合起来,不能求出每个 \(dp_i\),显然这样做的复杂度下界就是 \(O(n)\)。DDP 的本质上是把中间转移和中间结果压掉了。

  • 总复杂度 \(O(m\log n\times 3^3)\),大概能过 \(10^5\) 的数据。

  • 我们发现这个矩阵非常空,足有 \(4\) 格没有意义。说明我们有点浪费,设法深挖线段树的潜力,我们搞一个纯用复杂线段树维护的:

    • 在每个节点维护 \(mx,lf,rg,sum\) 表示区间最大子段和,左起最大子段和,右起最大子段和,区间和。

    • 写一个复杂的 pu,这里不想写了可以参看 \(\text{P4513 小白逛公园}\) 的代码。询问的时候,返回值设计成一个 node,套用这种合并方式。

    • 核心在于什么呢?相当于我们把 dp 的形式又改了改,以重构它原来的从左向右的顺序,变成了类似于 \(((),()),((),())\) 的形式。这就满足只靠线段树维护的需求。

22.10.10 T3 mountains

  • 版权原因,请移步查看。

P4719 【模板】"动态 DP"&动态树分治

  • 题意:给出一棵 \(n\) 个点的带点权树,有 \(m\) 次单点修改点权的操作,请在每次修改后求最大权独立集的权。

  • 数据范围:\(n,m\leqslant 10^5\)。

  • 老规矩,先考虑怎么静态 DP。这个东西显然非常 tdp,考虑这么做:

    • 状态设计:\(dp_{i,0/1}\) 表示考虑完 \(i\) 的子树,选/不选 \(i\) 的情况下的最大权独立集的权。

    • 初始化:\(dp_{i,0}=0,dp_{i,1}=w_i\)。

    • 状态转移方程:

      • \(dp_{i,0}=\sum\limits_{j\in \text{sons of i}} \max(dp_{j,0},dp_{j,1})\)。

      • \(dp_{i,1}=\sum\limits_{j\in \text{sons of i}}dp_{j,0}+w_i\)。

  • 这个东西是 \(O(n)\) 的,很好。我们考虑把它改成 \(O(n\log)\) 的在线做法。

  • 然而我们显然不能对着树直接做结合——单链的情况下,结合就会到达 \(n\) 次,无法接受。

  • 注意到这个转移中各个儿子其实互相没有影响。我们考虑把树的结构改成更可合并一些的结构:轻重剖!

  • 如果我们能做到仅在每个虚边上做一次合并,那么我们的复杂度显然就对了。

  • 所以考虑重新设计 DP。

    • 状态设计:\(f_{i,0/1},g_{i,0/1}\)。其中 \(f\) 相当于 \(dp\),\(g\) 则表示只考虑轻儿子和自己的情况下的最大权。

    • 初始化:区别不大,略。

    • 状态转移方程:

      • \(g_{i,0}=\sum\limits_{j\in \text{light sons of i}} \max(f_{j,0},f_{j,1})\)。

      • \(g_{i,1}=\sum\limits_{j\in \text{light sons of i}}f_{j,0}+w_i\)。

      • \(f_{i,0}=g_{i,0}+\max(f_{hs,0},f_{hs,1})\)。

      • \(f_{i,1}=g_{i,1}+f_{hs,0}\)。

  • 这里不妨假设我们手上已经有了全套的 \(g\)。设法把 \(f\) 的转移写成矩乘的形式:

    • 状态矩阵:\(\begin{bmatrix}f_{i,0} & f_{i,1}\end{bmatrix}\)。这里 \(i\) 可以认为就是 \(i+1\) 的 \(hs\)。

    • 乘法法则:\(res_{i,j}=\max_{k=1}^m(A_{i,k}+B_{k,j})\)。

    • 转移矩阵:\(\begin{bmatrix} g_{i+1,0} & g_{i+1,1}\\ g_{i+1,0} & -\infty\end{bmatrix}\)。嗯,这是和原转移方程等价的。

  • 那么我们只要将树剖好,单点修改的时候先修矩阵做到链头,然后用增量法暴力算一下 \(g_{fa_{top}}\),再修一下矩阵,一路做回去就对了。

  • 复杂度 \(O(na^3\log^2 n)\),但是树剖实在是快得飞起。

  • 这东西把我写吐了...

    • 每个重链要单独开 sgt 否则和我们需要的合并方式不一样(除非用区间询问,但那也太鬼了)。

    • 对链维护的其实是转移矩阵 \(G\) 的连乘,\(F\) 需要的时候才拎出来。事实上只维护了重链头和尾处的 \(F\)...当然,实现是比较随意的事情。

    • 把 \(F\) 初始化成一元以便于它和自己的 \(G\) 相乘。本来想的是按需求放各种一元,但实际上好像没有怎么用到。

    • 不断地记录 \(w,f,g\) 以便于使用增量法,或者说算 \(\Delta\)。

    • 总之就是非常恶心。

P5024 [NOIP2018 提高组] 保卫王国

  • 题意:给出一棵 \(n\) 个点的带点权树。给出 \(m\) 个询问,每个询问会钦定 \(2\) 个点分别必选/不选,求该前提下的最小权点覆盖的权。

  • 数据范围:\(n,m\leqslant 10^5\)。

  • 怎么这么喜欢把 DDP 搬到树上啊!还都是很图论基础概念的东西...

  • 我们还是来设法先设计一个静态 DP。

    • 状态设计:\(dp_{i,0/1}\) 表示考虑完 \(i\) 的子树,选/不选 \(i\) 的前提下,最小权点覆盖的权。

    • 初始化:\(dp_{leaf,1}=w_i\)。

    • 状态转移方程:

      • \(dp_{i,0}=\sum\limits_{j\in \text{sons of i}} dp_{j,1}\)。

      • \(dp_{i,1}=\sum\limits_{j\in \text{sons of i}} \min(dp_{j,0},dp_{j,1})+w_i\)。

  • 我真是欲言又止止言又欲...这不就是上面那个的镜像吗...哦不全是是吧?

  • 尽管贺自己的东西并没什么,但我们还是最好把这玩意搞懂吧...深蓝,给我推式子!(???)

  • 还是考虑用重剖来解决这玩意。首先乱七八糟重剖一下,然后我们重新设计 \(dp\) 状态:

    • 状态设计:\(f_{i,0/1},g_{i,0/1}\)。意义参前。

    • 初始化:略。

    • 状态转移方程:

      • \(g_{i,0}=\sum\limits_{j\in \text{sons of i}} f_{j,1}\)。

      • \(g_{i,1}=\sum\limits_{j\in \text{sons of i}} \min(f_{j,0},f_{j,1})+w_i\)。

      • \(f_{i,0}=g_{i,0}+f_{hs,1}\)。

      • \(f_{i,1}=g_{i,1}+\min(f_{hs,0},f_{hs,1})\)。

  • 确实是...很一样呢,哈哈哈(棒读)。让我看看剧本...哦该拆矩阵了是吧...好...

    • 状态矩阵:\(\begin{bmatrix} f_{i,0} & f_{i,1}\end{bmatrix}\)。

    • 乘法法则:唔,这里用 \(\min\) 就可以了。

    • 转移矩阵:\(\begin{bmatrix} +\infty & g_{i+1,1} \\ g_{i+1,0} & g_{i+1,1}\end{bmatrix}\),这里认为 \(i=hs_{i+1}\)。

  • 后面显然都一样了。你就当是一道非常难写的水紫吧...毕竟上面那份代码还在可以改改就用对吧,啊哈哈哈(棒读)。

  • 什么,不是单点修改?什么不是单点修改,就是单点修改!必选就是 \(-\infty\),必不选就是 \(+\infty\),这不就完了?

  • 主要难搞的地方在于这个修改是...嗯...临时性的,你懂我意思吧?得记录一下,用完改回来。

为什么不用复杂线段树呢?

  • 两个理由:

    1. 难以实现;

    2. 缺乏优势。

  • 先谈实现难度。考察最大子段和和 mountains 两道题,发现两者的 DP 形式其实较简单,这一简单的含义如下:

    • 存在一种较为简洁的方式,可以将多次转移合并为一次。

    • 以最大子段和为例:

    \[\begin{aligned} dp_i & = \max(dp_{i-1}+v_i,v_i) \\ & = \max(\max(dp_{i-2}+v_{i-1},v_{i-1})+v_i,v_i) \\ &=\max(dp_{i-2}+v_{i-1}+v_i,v_{i-1}+v_i,v_i)\end{aligned} \]

  • 转头考察 P4719,首先我们得两个一起转移因为它们是互转的,然后!DP 状态将会非!常!恶!心!

    • \(g\) 的定义将变成“轻儿子和重链上不超出对应 sgt 节点管辖范围的部分”的最大权独立集的权。

    • 只有这样,我们才能符合线段树的形式地把重链 DP 出来,即扬弃链底-链头的顺序,改为在链上分治的 sgt 风格。

  • 再谈缺乏优势。

    • 大部分情况下,结合律优化用复杂 sgt 的转移近似于状态数的 \(^2\),而矩乘近似于 \(^3\)。

    • 实际情况中一般都会有溢出。

      • 先谈矩乘。
        • 较为典型的例子,譬如某些需要即时结算 \(ans\) 的题目,此时只能把 \(ans\) 也塞进矩阵,容易证明这会造成很多浪费(很多与 \(ans\) 相关的转移都是无效转移,用 \(+-\infty\) 顶掉的)。

        • 类似地,有时转移的系数 \(w\) 之类的也得塞进去。甚至有时状态矩阵里要放 \(0\) 来占位...

        • 有并行转移的 DP 就更不用说了,举个例子,\(3^2+5^2\) 的复杂度能暴涨到 \(8^3\)。

        • 矩乘有这么多无效转移,很大程度上就说明了它是一种很粗放的实现方式。但如果矩阵很小,那么它的表现还是挺不错的。

        • 再谈复杂 sgt。

          • 复杂 sgt 本身的分治要求有时对 DP 本身的固有顺序破坏很大。譬如这里就要被迫重新定义,还得同时跑 \(f,g\),作为对比矩乘只需要做 \(G\)。

          • 转移本身系数大点是很正常的事情。

    • 综上,这里 \(2^3\) 并不比 \(2^2\) 差多少,这还没有考虑 sgt 自己的各种额外系数。所以啊,矩乘码量大却简单啊!

P8820 [CSP-S 2022] 数据传输

  • 参看树形 DP-难以形容的其他树上依赖式问题。

标签:...,max,矩阵,DP,结合律,优化,转移,dp
From: https://www.cnblogs.com/weixin2024/p/17077127.html

相关文章

  • 如何将WebAssembly优化到2MB?
    BlazorWebAssembly加载优化方案对于BlazorWebAssembly加载方案的优化是针对于WebAssembly首次加载,由于BlazorWebAssembly是在首次加载的时候会将.NETCore的所有程序集......
  • Layabox的2d精灵的性能优化
    在使用Layabox的2d精灵时,我们会需要很多渲染图片的需求,那么,如果做到使用最小的代价实现图片的渲染呢。合并图集为什么要合并图集呢。如果你一个图片是由多张图片组成的,正常......
  • Echarts Tooltip的大量数据下显示优化
    前言在做某些图表需求的时候,有时候需要让echartstooltip展示大量内容,这些内容如果按照echarts默认的显示方式,会出现超出屏幕的部分溢出,展示不全问题.解决这个问题呢,......
  • VMware安装Rocky Linux8服务器系统并执行优化,包括修改安装镜像源、ssh免密等等
    1、https://blog.csdn.net/DCTANT/article/details/125430461?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-1-125430......
  • centos 7 系统优化
    #系统版本CentOSLinuxrelease7.9.2009(Core)x64#内核版本Linuxdashuju013.10.0-1160.el7.x86_64#1SMPMonOct1916:18:59UTC2020x86_64x86_64x86_64GN......
  • 通过 explain 关键字对sql进行优化
    在select语句之前增加explain关键字,MySQL会在查询上设置一个标记,执行查询时,会返回执行计划的信息,而不是执行这条SQL(如果from中包含子查询,仍会执行该子查询,将结果放......
  • allure-动态参数,报告优化方法。
    1.allure.title方法#前置需要在源文件:\venv\Lib\site-packages\allure_pytest\listener.py#在该文件修改为这样:test_result.parameters.extend([])#使用方法:allure.dyna......
  • 高并发环境下3种方式优化Tomcat性能
    摘要:Tomcat作为最常用的JavaWeb服务器,随着并发量越来越高,Tomcat的性能会急剧下降,那有没有什么方法来优化Tomcat在高并发环境下的性能呢?本文分享自华为云社区《【高并发】......
  • CocosCreator 性能优化:DrawCall
    在游戏开发中,DrawCall作为一个非常重要的性能指标,直接影响游戏的整体性能表现。无论是CocosCreator、Unity、Unreal还是其他游戏引擎,只要说到游戏性能优化,DrawCall都......
  • 高并发环境下3种方式优化Tomcat性能
    摘要:Tomcat作为最常用的JavaWeb服务器,随着并发量越来越高,Tomcat的性能会急剧下降,那有没有什么方法来优化Tomcat在高并发环境下的性能呢?本文分享自华为云社区《​​【高并发......