【优化】单调队列与dp
笔者大概看了一下单调队列对于DP的优化,故撰此文,望有帮助。
(dp还是推式子难啊qwq)
题目大意:在n个数的序列中,选择数字,使得其连续不超过k个数,且和最大。
本题的方程相对好推:设dp[i][0/1]为到了第i个数,且第i个数不选/选的最大值。
则有转移:dp[i][0]=max(dp[i-1][0],dp[i-1][1])
dp[i][1]=max{dp[j][0]-sum[j]+sum[i]},i-k<=j<i
枚举j即可。
但是题目会这么让你水过吗?
发现会超时,优化不可避免。
仔细观察方程,考虑它的特殊性。
对于方程1,我们不便再多做什么。但是对于方程2,显然仍有优化余地。
我们将sum[i]提出来,得到:
dp[i][1]=max{dp[j][0]-sum[j]}+sum[i].
这个方程只与j有关,我们让max里面的最大就好了。
维护它,我们可以用堆,也可以用单调队列,线段树。
本文主要讲对于单调队列的优化。它可以保证O(n)的时间复杂度。
首先,我们明确一点,我们维护的队首元素最大。显然,队列中的数字要单调递减。
其次,我们要严格确保我们查询的区间,保证队列中没有没用的数字。
并且每次枚举到下一个数的时候,注意更新队列。
考虑何时更新更优:
首先,当这个数字不在需要的范围的时候,删除即可。
其次,对于新插入的数字,我们要从队尾插入,比较哪个值更优:
判断它们的“浪费情况”即可。
用q[]表示队列,s[]表示前缀和,则判断:
s[q[head]]-f[q[head]][0]>s[i]-f[i][0]&&head<=tail
如果符合的话,就把它删掉吧。因为队尾的元素所浪费的比新插入的值多,显然一定不如它优。
由此,我们已经保证了单调队列的稳定复杂度。
给出代码:
#include<cstdio>
#include<iostream>
using namespace std;
long long q[2000000],f[2000000][2];
long long n,k,s[2000000],a[2000000];
long long tail,head;
int main(){
scanf("%lld%lld",&n,&k);
for(int i=1;i<=n;++i){
scanf("%lld",&a[i]);
s[i]=s[i-1]+a[i];//sum
}
tail=head=1;//初始化
for(int i=1;i<=n;++i){
f[i][0]=max(f[i-1][0],f[i-1][1]);//对于不选i,只考虑前面两个即可
while(q[head]<i-k&&head<=tail)head++;//判断队头是否在所找区间内
f[i][1]=f[q[head]][0]-s[q[head]]+s[i];//取MAX转移
while(f[i][0]-s[i]>f[q[tail]][0]-s[q[tail]]&&head<=tail)tail--;
q[++tail]=i;//更新队尾,当队列有数且当前队尾若插入i不满足单调性时
//写成s[i]-f[i][0]<s[q[tail]]-f[q[tail]][0]也可以
//可以理解为选到i和队尾时,两者不选的奶牛的效率和相比较,显然浪费少的更优,不优的删除即可
}printf("%lld\n",max(f[n][0],f[n][1]));
return 0;
}
双倍经验:P2034
持续更新中。
【优化】单调队列与dp的更多相关文章
- 【题解】Cats Transport (斜率优化+单调队列)
[题解]Cats Transport (斜率优化+单调队列) # When Who Problem Lang Verdict Time Memory 55331572 Jun/09/2019 19:1 ...
- BZOJ_1999_[Noip2007]Core树网的核_单调队列+树形DP
BZOJ_1999_[Noip2007]Core树网的核_单调队列+树形DP Description 设T=(V, E, W) 是一个无圈且连通的无向图(也称为无根树),每条边带有正整数的权,我们称T ...
- 【刷题笔记】DP优化-单调队列优化
单调队列优化 眼界极窄的ZZ之前甚至不会单调队列--(好丢人啊) 单调队列优化的常见情景: 转移可以转化成只需要确定一个维度,而且这个维度的取值范围在某个区间里 修剪草坪 这个题学长讲的好像是另外一个 ...
- BZOJ.1010.[HNOI2008]玩具装箱toy(DP 斜率优化/单调队列 决策单调性)
题目链接 斜率优化 不说了 网上很多 这的比较详细->Click Here or Here //1700kb 60ms #include<cstdio> #include<cc ...
- 完美字符子串 单调队列预处理+DP线段树优化
题意:有一个长度为n的字符串,每一位只会是p或j.你需要取出一个子串S(注意不是子序列),使得该子串不管是从左往右还是从右往左取,都保证每时每刻已取出的p的个数不小于j的个数.如果你的子串是最长的,那 ...
- [bzoj1010](HNOI2008)玩具装箱toy(动态规划+斜率优化+单调队列)
Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有 的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1.. ...
- Luogu【P1725】琪露诺(单调队列,DP)
本文是笔者第二篇解题报告.从现在开始,会将练的一些题发到博客上并归类到"解题报告"标签中. 琪露诺是这样一道题 这道题可以用纯DP做,但是据说会超时.(为什么?看起来过河这题比它数 ...
- 单调队列与DP
算是一个总结吧! 先来一个模板: TYVJ 1305 最大子序和 题目描述 输入一个长度为n的整数序列,从中找出一段不超过M的连续子序列,使得整个序列的和最大. 例如 1,-3,5,1,-2,3 当m ...
- 单调队列+线性dp题Watching Fireworks is Fun (CF372C)
一.Watching Fireworks is Fun(紫题) 题目:一个城镇有n个区域,从左到右1编号为n,每个区域之间距离1个单位距离节日中有m个烟火要放,给定放的地点ai,时间ti当时你在x,那 ...
随机推荐
- A little something to get you started(Hacker101 CTF)
打开题目的页面发现只有”Welcome to level 0. Enjoy your stay.“这么一行普通的文字,然后习惯性的打开浏览器的开发者工具的“network”模块,按下F5发现网页在请求 ...
- 分享一个后端专用login模板
给大家啊分享一个后端专用login模板 Java工程师再也不用这样啦---> html源码 <html lang="en"> <head> <m ...
- Java程序取MySQL的datetime字段,如何消除时间尾后讨厌的".0"
Problem: 直接取datetime字段的内容会有".0"后缀,如2020-05-03 18:21:39.0,虽无伤大雅但总觉得有些别扭. Solution:使用转化函数Dat ...
- python连接websocket wss
def websocket_wss(): try: wss = create_connection(wss_url, timeout=10) if wss.status == 101: wss.sen ...
- oracle之三 自动任务调度
Oracle 自动任务调度 13.1 Oracle任务调度概述 在Oracle中任务调度指某一(组)执行程序在特定的时间被周期性的执行.Oracle把任务调度称为job(作业). Advanced S ...
- [LeetCode]121、122、309 买股票的最佳时机系列问题(DP)
121.买卖股票的最佳时机 题目 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. 如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润. 注意 ...
- [SSM项目]三-日志Logback
Logback介绍 Logback的主要模块 logback-access :与service容器集成,提供通过http访问日志的功能.即第三方软件可以通过这个模块来访问日志. logback-cla ...
- .NetCore之接口缓存
1.问题:我们平时做开发的时候肯定都有用到缓存这个功能,一般写法是在需要的业务代码里读取缓存.判断是否存在.不存在则读取数据库再设置缓存这样一个步骤.但是如果我们有很多地方业务都有用到缓存,我们就需要 ...
- vue项目中使用ts(typescript)入门教程
最近项目需要将原vue项目结合ts的使用进行改造,这个后面应该是中大型项目的发展趋势,看到一篇不错的入门教程,结合它并进行了一点拓展记录之.本文从安装到vue组件编写进行了说明,适合入门. 1.引入T ...
- Linux实战(2):Linux传输文件
此次使用的是scp命令,只是针对文件或者文件的传输,并没有什么高端的使用,主要是怕自己忘记了记一下. 传输文件,命令说明:scp+文件路径针确到文件名+账号+上传到另一台的路径并另存为文件名 scp ...