I.导入:

这是一个\(O(n^2)\)的状态和转移方程:

\[f(i,j)=\left\{
\begin{aligned}
f(i-1,j-1)+k \ (1\leq j)\\
\max_{k \in [0,i]}{f(i-1,k)} (j=1)
\end{aligned}
\right.\]

这个方程目测是\(\Theta(n^2)\)的,但是实际上,上面的那个方程只是把数组整体位移了,下面的方程只是在位移后的数组开端添上了一个数,这个完全可以通过队列来实现,\(+k\)的操作,用一个整体的差分量就能实现,时间复杂度\(O(n)\)。这个方法最伟大的一点在于,它的复杂度比状态维度还要低一维,这是让人难以想到这种方法的一大原因。

II.xj2020 画画

\(n<=5000, m<=1e7\).显然当两种颜色的 a 相等的时候,它们完全等价,所以我们建一个桶 \(b_i\) 表示长度限制为 i 的颜色个数,再设\(f_{i,j,k}\)表示 DP 到了 i 号格子,当前颜色的长度限制是 j (其实是有点 hash 的表示颜色),当前颜色已经连续了 k 个,则状态转移方程为:

\[f(i,j,k)=\left\{
\begin{aligned}
f(i-1,j,k-1) \ (1\leq k)\\
b_j\sum_{j'!=j}{\sum_{k'}{f(i-1,j',k')}} + (b_j-1)\sum_{k'}{f(i-1,j,k')} (j=1)
\end{aligned}
\right.\]

这个状态状态转移方程上面和下面各是\(\Theta(n^3)\)的,但是我们可以发现这个转移方程,上面的可以用队列来实现整体位移,下面的可以对每个队列维护一个和,再维护一下总和,就能实现\(\Theta(n^2)\)了,主要代码如下:

for (int i = 1; i <= n; i++)
{
q[i].push(b[i]);
lastsum += (S[i] = b[i]);
}
for (int i = 2; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if (!b[j]) continue;
ins[j] = ((LL)lastsum * b[j] % mod + mod - S[j]) % mod;
}
for (int j = 1; j <= n; j++)
{
if (!b[j]) continue;
(S[j] += ins[j]) %= mod;
(lastsum += ins[j]) %= mod;
q[j].push(ins[j]);
}
for (int j = 1; j <= n; j++)
{
if (!b[j]) continue;
while (q[j].size() > j)
{
(S[j] += mod - q[j].front()) %= mod;
(lastsum += mod - q[j].front()) %= mod;
q[j].pop();
}
}
}
fout << lastsum << Endl;

实现难度不大,主要难度在于设出状态和方程,因为这个状态有三维,很多时候我们就默认它的时间复杂度大于等于三次方,而这题偏偏又很容易得到只有两维的状态设置,很多人以为“肯定不如二维的状态设置”,但实际上,这个三维的状态可以优化到二次方,而这个二维的状态设置没法实现\(\Theta(1)\)的转移

III.xj2020 字符串

\(n<=2e5,m<=20\).假设 DP 到了前 i 个点,当前的两个子序列,一个肯定有一个以 i 号字符串结尾,我们只需要存另一个子序列以什么结尾;而子序列的长度都相同,说明我们只关心这个子序列最后一个串是哪一个。设\(f[i][j]\)表示,DP 到了前 i 个点,一个子序列的结尾是 i,另一个子序列的结尾是 j 时的最短长度。综合把 i 接到 i-1 上 和把 i 接到 i-1 之前的两种情况,可以得到状态转移方程:

\[f(i,j)=\left\{
\begin{aligned}
\min\{f(i-1,k)+cost(k,i)\} \ (j=i-1)\\
f(i-1,k)+\text{cost}(i-1,i)(else)
\end{aligned}
\right.\]

这个状态转移方程本身已经很难想到了,需要很熟稔的分类讨论的能力。优化上,可以使用栈——上面那东西是整体加法,下面那东西是在栈底追加一个值。考虑这个 min 怎么\(\Theta(1)\)求:对于 cost 相等的 k ,显然它们是等价的。所以把已有的字符串倒序放进一个 Trie 里面,查询时正着顺着 \(S_i\) 走,每到一个点用\(m-dep+f_X\)更新答案,其中\(f\)是树上前缀最小值,这样会有重复情况,但是显然不影响。用整体差分就能实现 f 值的修改。

IV.「2020-09-20 五校联考」球与洞 (ballhole)

这个是国冬模拟费用流的第二题,居然被搬来了五校联考。。。

首先使用微扰法,把球和洞画成两排,把每个球连向它的洞,显然这些连线不能相交,这就及其有利于我们进行 DP。把球和洞摆成一排并排序,设\(f[i][i]\)表示,当 \(j>0\)时表示剩下确定选下了 \(-j\)个洞待匹配的最小代价;当 \(j<0\)时表示 DP 到了第 \(i\) 个位置、剩下多少个球还待匹配的、费用提前计算的代价(提前减去绝对值函数的部分呀),那么当前位置是个球的时候,状态转移方程是:

\[f(i,j)=f(i-1,j+1)+\left\{
\begin{aligned}
-pos_i \ (j>0)\\
pos_i (else)
\end{aligned}
\right.\]

当目前位置是个洞的时候,状态转移方程就是:

\[f(i,j)=min(f(i-1,j),f(i-1,j-1)+\left\{
\begin{aligned}
-pos_i \ (j<0)\\
pos_i (else)
\end{aligned})
\right.\]

然后把第二个式子分析一下,发现当且仅当\(j=0\)的时候需要取 min, 其他时候只需要直接取右手边的作为最小值即可,所以我们把 DP 数组切成三段,下标是负的一段,0一段,正的一段,就可以实现 \(\Theta(n)\)。评测记录

总结:有的时候转移的复杂度比较大/状态的维度比较大的时候,我们不妨退而求其次,通过把状态升一维的代价把转移降低一维,也许就可以通过队列优化,反而能优化掉一维。

一类利用队列优化的DP的更多相关文章

  1. hdu-3401-Trade-单调队列优化的DP

    单调队列入门题... dp[i][j]:第i天.手中拥有j个股票时,获得的最大利润. 若第i天不买不卖:dp[i][j]=max(dp[i][j],dp[i-1][j]); 若第i天买         ...

  2. 【NOIP2017】跳房子 题解(单调队列优化线性DP)

    前言:把鸽了1个月的博客补上 ----------------- 题目链接 题目大意:机器人的灵敏性为$d$.每次可以花费$g$个金币来改造机器人,那么机器人向右跳的范围为$[min(d-g,1),m ...

  3. Trade-----HDU3401----单调队列优化的DP

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=3401 题目意思: 有T天,你每天可以以API买进,BPI卖出,最多买ASI个,最多卖BSI个 最多只能 ...

  4. poj1821 Fence【队列优化线性DP】

    Fence Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 6122   Accepted: 1972 Description ...

  5. 洛谷p1725 露琪诺 单调队列优化的DP

    #include <iostream> #include <cstdio> #include <cstring> using namespace std; int ...

  6. BestCoder Round #89 02单调队列优化dp

    1.BestCoder Round #89 2.总结:4个题,只能做A.B,全都靠hack上分.. 01  HDU 5944   水 1.题意:一个字符串,求有多少组字符y,r,x的下标能组成等比数列 ...

  7. 单调队列以及单调队列优化DP

    单调队列定义: 其实单调队列就是一种队列内的元素有单调性的队列,因为其单调性所以经常会被用来维护区间最值或者降低DP的维数已达到降维来减少空间及时间的目的. 单调队列的一般应用: 1.维护区间最值 2 ...

  8. bzoj1855: [Scoi2010]股票交易 单调队列优化dp ||HDU 3401

    这道题就是典型的单调队列优化dp了 很明显状态转移的方式有三种 1.前一天不买不卖: dp[i][j]=max(dp[i-1][j],dp[i][j]) 2.前i-W-1天买进一些股: dp[i][j ...

  9. 队列优化和斜率优化的dp

    可以用队列优化或斜率优化的dp这一类的问题为 1D/1D一类问题 即状态数是O(n),决策数也是O(n) 单调队列优化 我们来看这样一个问题:一个含有n项的数列(n<=2000000),求出每一 ...

随机推荐

  1. [no_code][Beta]设计和计划

    2020春季计算机学院软件工程(罗杰 任健) 2020春季计算机学院软件工程(罗杰 任健) 作业要求 Beta设计和计划 我们在这个课程的目标是 远程协同工作,采用最新技术开发软件 这个作业在哪个具体 ...

  2. Alpha阶段初始任务分配

    项目 内容 这个作业属于哪个课程 2021春季软件工程(罗杰 任健) 这个作业的要求在哪里 团队项目-计划-Alpha阶段说明书 一.Alpha阶段总体规划 进行服务器相关部署 进行开发相关技术学习 ...

  3. 对mongo文档的增删改操作

    在mongo db 中增加.删除.修改文档有好多方法,这里简单记录一下我所知道的一些方法. 前置条件: 1.创建study数据库  use study; 2.创建persons集合,当第一次向pers ...

  4. 2021.8.12考试总结[NOIP模拟37]

    T1 数列 考场上切掉的简单题. $a$,$b$与数列中数的正负值对答案无关.全当作正数计算即可. $exgcd$解未知数系数为$a$,$b$,加和为$gcd(a,b)$的不定方程组,再枚举每个数.如 ...

  5. Python环境配置详细步骤以及第一个程序

    打开python官网:https://www.python.org/ 在官网找与自己电脑系统匹配的版本路径  这里以python3.7.2版本为例: 下载完成后,使用管理员身份进行安装:  打开命令提 ...

  6. 超级好用的轻量级JSON处理命令jq

    1 简介 jq是一个轻量级的命令行工具,让你可以非常方便地处理JSON数据,如切分.过滤.映射.转化等,就像sed.awk.grep文本处理三剑客一样.jq是用C写的,没有运行时依赖,你可以直接下载可 ...

  7. 从零开始的DIY智能家居 - 基于 ESP32 的土壤湿度传感器

    前言 自从上次做了那个 甲醛传感器 和 水浊度传感器 之后开始尝到智能家居的甜头了,这两东西有没有用我不知道,但是没事的时候掏出手机瞄两眼,看着就让人很安心( ̄︶ ̄). 于是懒惰的我开始琢磨把给植物浇 ...

  8. python doc os 参考

    os --- 操作系统接口模块 源代码: Lib/os.py 该模块提供了一些方便使用操作系统相关功能的函数. 如果你是想读写一个文件,请参阅 open(),如果你想操作路径,请参阅 os.path  ...

  9. 第10课 OpenGL 3D世界

    加载3D世界,并在其中漫游: 在这一课中,你将学会如何加载3D世界,并在3D世界中漫游.这一课使用第一课的代码,当然在课程说明中我只介绍改变了代码. 这一课是由Lionel Brits (βtelge ...

  10. Spring Cloud Alibaba环境搭建

    前言:Spring Cloud Alibaba是目前主流的分布式微服务架构,本文主要讲解了在IDEA中如何搭建Spring Cloud Alibaba环境,以及介绍Spring Cloud Aliba ...