单调队列java_浅谈单调队列优化dp
单调队列,即单调的队列。有时用于优化1D/1D方程。
例题 Tyvj1305
时间: 1000ms / 空间: 131072KiB / Java类名: Main
描述
输入一个长度为n的整数序列,从中找出一段不超过M的连续子序列,使得整个序列的和最大。
例如
1,-3,5,1,-2,3
当m=4时,S=5+1-2+3=7
当m=2或m=3时,S=5+1=6
输入格式
第一行两个数n,m
第二行有n个数,要求在n个数找到最大子序和
输出格式
一个数,数出他们的最大子序和
测试样例
输入
6 4
1 -3 5 1 -2 3
输出
7
备注
数据范围:
100%满足n,m<=300000
分析
这是一个典型的动态规划题目,不难得出一个1D/1D方程:
f(i) = sum[i]-min{sum[k]|i-M≤k≤i}
如果不明白这个方程的来历,戳这里
由于方程是1D/1D的,所以我们不想只得出简单的Θ(n^2)算法。不难发现,此优化的难点是计算min{sum[i-M]..sum[i-1]}。在上面的链接中,我们成功的用Θ(nlgn)的算法解决了这个问题。但如果数据范围进一步扩大,运用st表解决就力不从心了。所以我们需要一种更高效的方法,即可以在Θ(n)的摊还时间内解决问题的单调队列。
单调队列(Monotone queue)是一种特殊的优先队列,提供了两个操作:插入,查询最小值(最大值)。它的特殊之处在于它插入的不是值,而是一个指针(key)(wiki原文:imposes the restriction that a key (item) may only be inserted if its priority is greater than that of the last key extracted from the queue)。所谓单调,指当一组数据的指针1..n(优先级为A1..An)插入单调队列Q时,队列中的指针是单调递增的,队列中指针的优先级也是单调的。因为这里要维护优先级的最小值,那么队列是单调减的,也说队列是单调减的。
查询最小值
由于优先级是单调减的,所以最小值一定是队尾元素。直接取队尾即可。
插入操作
当一个数据指针i(优先级为Ai)插入单调队列Q时,方法如下:
如果队列已空或队头的优先级比Ai大,删除队头元素。
否则将i插入队头
比如说,一个优先队列已经有优先级分别为 {5,3,-2} 的三个元素,插入一个新元素,优先级为2,操作如下:
因为2 < 5,删除队头,{3,-2}
因为2 < 3,删除队头,{-2}
因为2 > -2,插入队头,{2,-2}
证明性质可以得到维护
证明指针的单调减 :由于插入指针i一定比已经在队列中所有元素大,所以指针是单调减的。
证明优先级的单调减:由于每次将优先级比Ai大的删除,只要原队列优先级是单调的,新队列一定是单调的。用循环不变式易证正确性。
为什么删除队头:直观的,指针比i小(靠左)而优先级比Ai大的数据没有希望成为任何一个需要的子序列中的最小值。这一点是我们使用优先队列的根本原因。
维护区间大小
当一串数据A1..Ak插入时,得到的最小值是A1..Ak的最小值。反观dp方程:
f(i) = sum[i]-min{sum[k]|i-M≤k≤i}
在这里,A = sum。对于f(i),我们需要的其实是Ai-M .. Ai的最小值,而不是所有已插入数据的最小值(A1..Ai-1)。所以必须维护区间大小,使队列中的元素严格处于Ai-M..Ai-1这一区间,或者说删去哪些A中过于靠前而违反题目条件的值。由于队列中指针是单调的,也就是靠左的指针大于靠右的,或者说在优先队列中靠左的值,在A中一定靠后;优先队列中靠右的值,在A中一定靠前。我们想要删除过于靠前的,只需要在优先队列中从右一直删除,直到最右边(队尾)的值符合条件。具体地:当队头指针p满足i-m≤p时。
形象地说,就是忍痛割爱删去哪些较好但是不符合题目限制的数据。
解决问题
这里用std::list表示队列,直接按照上面的方法查询最小值,然后根据方程,f(k) = s[i] - s[queue.back()]。直接给出代码:
#include
#include
#include
using namespace std;
int n, m;
long long s[300005];
// 前缀和
list queue;
// 链表做单调队列
int main() {
cin >> n >> m;
s[0] = 0;
for (int i=1; i<=n; i++) {
cin >> s[i];
s[i] += s[i-1];
}
long long maxx = 0;
for (int i=1; i<=n; i++) {
while (!queue.empty() and s[queue.front()] > s[i])
queue.pop_front();
// 保持单调性
queue.push_front(i);
// 插入当前数据
while (!queue.empty() and i-m > queue.back())
queue.pop_back();
// 维护区间大小,使i-m >= queue.back()
if (i > 1)
maxx = max(maxx, s[i] - s[queue.back()]);
else
maxx = max(maxx, s[i]);
// 更新最值
}
cout << maxx << endl;
return 0;
}
分析时间复杂度
运用聚合分析,由于一个元素最多进队一次,出队一次,while循环总共最多运行Θ(2n)=Θ(n)次,所以算法的摊还效率是Θ(n)。通过单调队列,实现了在线性复杂度内解决形如:
f[x] = max or min{g(k) | b[x] <= k < x} + w[x]
其中b[x]随x单调不降,即b[1]<=b[2]<=b[3]<=...<=b[n]
g[k]表示一个和k或f[k]有关的函数,w[x]表示一个和x有关的函数
的动态规划问题。
单调队列java_浅谈单调队列优化dp相关推荐
- 浅谈消息队列及常见的分布式消息队列中间件
背景 分布式消息队列中间件是是大型分布式系统不可缺少的中间件,通过消息队列,应用程序可以在不知道彼此位置的情况下独立处理消息,或者在处理消息前不需要等待接收此消息.所以消息队列主要解决应用耦合.异步消 ...
- 【转载】运维角度浅谈MySQL数据库优化
运维角度浅谈MySQL数据库优化 2015-06-02 14:22:02 标签:mysql优化 mysql分库分表分区 mysql读写分离 mysql主从复制 原创作品,允许转载,转载时请务必以 ...
- 浅谈尾递归的优化方式
在上文<尾递归与Continuation>里,我们谈到了尾递归的概念和示例,不过有些朋友对于尾递归的功效依然有所怀疑.因此现在,我再简单讲解一下尾递归的优化原理,希望能给大家以一定理性认识 ...
- 浅谈SEO的优化问题
浅谈SEO的优化问题 文章目录 浅谈SEO的优化问题 简介 专业名词 提高排名的技巧 注: 感悟: 简介 SEO是搜索引擎优化(Search Engine Optimization)的英文缩写,中文译 ...
- 浅谈 AnalyticDB SQL 优化
浅谈 AnalyticDB SQL 优化 前言 ADB计算引擎 ADB优化器 ADB索引 ADB SQL开发与表分区设计 ADB SQL开发的性能指南 ADB慢SQL的定位和常见原因 ADB慢SQL优 ...
- 浅谈单调队列优化的DP
为什么都是浅谈?深入就掉坑啊,掉坑就要填坑啊,填坑就会发现又挖了更多的坑啊,然后恶性循环啊. 这个坑必须要填的,拖了这么久了. 先拿TYVJ 1305来说吧,此题具体的题面没找到,代码简单的对拍了一下 ...
- 浅谈DM数据库优化常识
今天谈一谈SQL的优化分享知识,在DBA的角度来看,数据库的优化一直是DBA一项很重要的工作,作为任何一门技术来说都应该本着"要想打败他必须先要了解他"的原则,其实,任何数据库的S ...
- 浅谈堡垒机优化的必要性-行云管家
堡垒机是确保企业网络安全的重要基础设施,已经应用于各行各业.但由于一些政策原因,以及系统自身原因,一些堡垒机已经无法满足需求,需要进行优化升级.今天我们就来浅谈一下堡垒机优化升级的必要性吧! 1.满足 ...
- 后端语言除了java_浅谈后端语言优缺点
浅谈后端语言优缺点 兄弟连教育在前不久,回答了一个关于后端语言选型的问题,那么后端语言都有哪些,存在什么样的优缺点?因此兄弟连与大家分享一下心得. 语言优缺点 C/C++ C 语言虽然是非常贴近操作系 ...
最新文章
- 时髦而精巧的Iphone墙纸收集
- Linux下基于密钥的安全验证实现方法
- .net mvc 报表_FastReport.Net已实现对.Net 5.0的支持
- system verilog随机函数_systemverilog中的随机化激励.pdf
- 【新书推荐】《ASP.NET Core微服务实战:在云环境中开发、测试和部署跨平台服务》 带你走近微服务开发...
- 妄想集合(牛客练习赛90)
- 民科微服务电脑版下载_天翼云桌面通用版电脑版下载|天翼云桌面通用版PC客户端 V1.23.0 官方最新版 下载_当下软件园...
- SQL Server 索引基础知识(1)--- 记录数据的基本格式
- C#网络编程之 UDP编程
- Html和Css学习笔记-html进阶-div与span
- Study 7 —— CSS美化背景和边框
- vision画流程图的软件_vision软件怎么画流程图
- Java SSM 商户管理系统 客户管理 库存管理 销售报表 项目源码
- python怎么输出roc曲线_如何用Python绘制ROC曲线
- samsung q1u android,奢华配置指纹科技 三星Q1U再造UMPC王者
- Time Limit Exceeded的原因及避免方法
- 设计模式——C++版
- Processing 案例 | 扑面而来的满天繁星
- WEEK 15 C ZJM 与纸条
- 05 -数据分析与SQL- Lesson5 SQL数据清理