一类利用队列优化的DP
I.导入:
这是一个\(O(n^2)\)的状态和转移方程:
\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 个,则状态转移方程为:
\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 之前的两种情况,可以得到状态转移方程:
\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\) 个位置、剩下多少个球还待匹配的、费用提前计算的代价(提前减去绝对值函数的部分呀),那么当前位置是个球的时候,状态转移方程是:
\begin{aligned}
-pos_i \ (j>0)\\
pos_i (else)
\end{aligned}
\right.\]
当目前位置是个洞的时候,状态转移方程就是:
\begin{aligned}
-pos_i \ (j<0)\\
pos_i (else)
\end{aligned})
\right.\]
然后把第二个式子分析一下,发现当且仅当\(j=0\)的时候需要取 min, 其他时候只需要直接取右手边的作为最小值即可,所以我们把 DP 数组切成三段,下标是负的一段,0一段,正的一段,就可以实现 \(\Theta(n)\)。评测记录
总结:有的时候转移的复杂度比较大/状态的维度比较大的时候,我们不妨退而求其次,通过把状态升一维的代价把转移降低一维,也许就可以通过队列优化,反而能优化掉一维。
一类利用队列优化的DP的更多相关文章
- hdu-3401-Trade-单调队列优化的DP
单调队列入门题... dp[i][j]:第i天.手中拥有j个股票时,获得的最大利润. 若第i天不买不卖:dp[i][j]=max(dp[i][j],dp[i-1][j]); 若第i天买 ...
- 【NOIP2017】跳房子 题解(单调队列优化线性DP)
前言:把鸽了1个月的博客补上 ----------------- 题目链接 题目大意:机器人的灵敏性为$d$.每次可以花费$g$个金币来改造机器人,那么机器人向右跳的范围为$[min(d-g,1),m ...
- Trade-----HDU3401----单调队列优化的DP
题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=3401 题目意思: 有T天,你每天可以以API买进,BPI卖出,最多买ASI个,最多卖BSI个 最多只能 ...
- poj1821 Fence【队列优化线性DP】
Fence Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 6122 Accepted: 1972 Description ...
- 洛谷p1725 露琪诺 单调队列优化的DP
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int ...
- BestCoder Round #89 02单调队列优化dp
1.BestCoder Round #89 2.总结:4个题,只能做A.B,全都靠hack上分.. 01 HDU 5944 水 1.题意:一个字符串,求有多少组字符y,r,x的下标能组成等比数列 ...
- 单调队列以及单调队列优化DP
单调队列定义: 其实单调队列就是一种队列内的元素有单调性的队列,因为其单调性所以经常会被用来维护区间最值或者降低DP的维数已达到降维来减少空间及时间的目的. 单调队列的一般应用: 1.维护区间最值 2 ...
- 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 ...
- 队列优化和斜率优化的dp
可以用队列优化或斜率优化的dp这一类的问题为 1D/1D一类问题 即状态数是O(n),决策数也是O(n) 单调队列优化 我们来看这样一个问题:一个含有n项的数列(n<=2000000),求出每一 ...
随机推荐
- C# 如何使用代码添加控件及控件事件
1.首先简单设计一下界面: 添加了Click事件 <Window x:Class="WpfApp.MainWindow" xmlns="http://schemas ...
- 【好好编程-技术博客】微信小程序开发中前后端的交互
微信小程序开发中前后端的交互 微信小程序的开发有点类似与普通网页的开发,但是也不尽然相同.小程序的主要开发语言是JavaScript,开发同普通的网页开发有很大的相似性,对于前端开发者而言,从网页开发 ...
- seata序列化日期类型出错
一.背景 最近在整合seata的过程中,发现如果业务表中存在 datetime 的数据类型,那么在分布式事务中,修改这个字段的值时,会出现如下错误.此处提供2种解决方案. com.fasterxml. ...
- 使用nexus搭建一个docker私服
使用nexus搭建docker私服 一.需求: 二.实现步骤 1.编写`docker-compose`文件,实现`nexus`的部署 2.修改/usr/lib/systemd/system/docke ...
- 震惊,hzoi的考试竟然折磨简单,活到爆!
众所周知,hzoi的考试题非常"简单",那么究竟有多简单呢?最近,一位外国小哥开发出了hzoi的考试竟然折磨简单,活到爆!的方法,这究竟是怎么一回事呢?快和小编一起来看看吧- 满分 ...
- mipi csi接口,1条lane支持多少像素,200w像素需要几条lane,为什么,怎么计算出来的?谢谢!
按帧频FRAME=60HZ, 分辨率480*800来计算;以WVGA 显示分辨率,24BIT图片,60幁为例,在理想状态下(未包含RGB信号前后肩宽度),总传输速率最小为:480*800*8BIT*3 ...
- 【做题记录】DP 杂题
P2577 [ZJOI2004]午餐 $\texttt{solution}$ 想到贪心: 吃饭慢的先打饭节约时间, 所以先将人按吃饭时间从大到小排序. 状态: \(f[i][j]\) 表示前 \(i\ ...
- 页表 Page tables
逻辑地址与物理地址的转化 页表是由页表项(PTE)组成的数组.512个PTE构成一个页表页(Page-table page). PTE中包含了物理页码(PPN physical page number ...
- AtCoder Beginner Contest 210题解
A B 过水,略... C 统计长度为k的区间的最多本质不同的数.用尺取法维护下左右指针就可以了.调了许久的原因是更新答案时出现了问题. 当我移动指针时,我们应该移动一个就更新一个,而不是将移动与更新 ...
- P2598 [ZJOI2009]狼和羊的故事(最小割)
P2598 [ZJOI2009]狼和羊的故事 说真的,要多练练网络流的题了,这么简单的网络流就看不出来... 题目要求我们要求将狼和羊分开,也就是最小割,(等等什么逻辑...头大....) 我们这样想 ...