单调队列,即单调的队列。有时用于优化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相关推荐

  1. 浅谈消息队列及常见的分布式消息队列中间件

    背景 分布式消息队列中间件是是大型分布式系统不可缺少的中间件,通过消息队列,应用程序可以在不知道彼此位置的情况下独立处理消息,或者在处理消息前不需要等待接收此消息.所以消息队列主要解决应用耦合.异步消 ...

  2. 【转载】运维角度浅谈MySQL数据库优化

     运维角度浅谈MySQL数据库优化 2015-06-02 14:22:02 标签:mysql优化   mysql分库分表分区 mysql读写分离 mysql主从复制 原创作品,允许转载,转载时请务必以 ...

  3. 浅谈尾递归的优化方式

    在上文<尾递归与Continuation>里,我们谈到了尾递归的概念和示例,不过有些朋友对于尾递归的功效依然有所怀疑.因此现在,我再简单讲解一下尾递归的优化原理,希望能给大家以一定理性认识 ...

  4. 浅谈SEO的优化问题

    浅谈SEO的优化问题 文章目录 浅谈SEO的优化问题 简介 专业名词 提高排名的技巧 注: 感悟: 简介 SEO是搜索引擎优化(Search Engine Optimization)的英文缩写,中文译 ...

  5. 浅谈 AnalyticDB SQL 优化

    浅谈 AnalyticDB SQL 优化 前言 ADB计算引擎 ADB优化器 ADB索引 ADB SQL开发与表分区设计 ADB SQL开发的性能指南 ADB慢SQL的定位和常见原因 ADB慢SQL优 ...

  6. 浅谈单调队列优化的DP

    为什么都是浅谈?深入就掉坑啊,掉坑就要填坑啊,填坑就会发现又挖了更多的坑啊,然后恶性循环啊. 这个坑必须要填的,拖了这么久了. 先拿TYVJ 1305来说吧,此题具体的题面没找到,代码简单的对拍了一下 ...

  7. 浅谈DM数据库优化常识

    今天谈一谈SQL的优化分享知识,在DBA的角度来看,数据库的优化一直是DBA一项很重要的工作,作为任何一门技术来说都应该本着"要想打败他必须先要了解他"的原则,其实,任何数据库的S ...

  8. 浅谈堡垒机优化的必要性-行云管家

    堡垒机是确保企业网络安全的重要基础设施,已经应用于各行各业.但由于一些政策原因,以及系统自身原因,一些堡垒机已经无法满足需求,需要进行优化升级.今天我们就来浅谈一下堡垒机优化升级的必要性吧! 1.满足 ...

  9. 后端语言除了java_浅谈后端语言优缺点

    浅谈后端语言优缺点 兄弟连教育在前不久,回答了一个关于后端语言选型的问题,那么后端语言都有哪些,存在什么样的优缺点?因此兄弟连与大家分享一下心得. 语言优缺点 C/C++ C 语言虽然是非常贴近操作系 ...

最新文章

  1. 时髦而精巧的Iphone墙纸收集
  2. Linux下基于密钥的安全验证实现方法
  3. .net mvc 报表_FastReport.Net已实现对.Net 5.0的支持
  4. system verilog随机函数_systemverilog中的随机化激励.pdf
  5. 【新书推荐】《ASP.NET Core微服务实战:在云环境中开发、测试和部署跨平台服务》 带你走近微服务开发...
  6. 妄想集合(牛客练习赛90)
  7. 民科微服务电脑版下载_天翼云桌面通用版电脑版下载|天翼云桌面通用版PC客户端 V1.23.0 官方最新版 下载_当下软件园...
  8. SQL Server 索引基础知识(1)--- 记录数据的基本格式
  9. C#网络编程之 UDP编程
  10. Html和Css学习笔记-html进阶-div与span
  11. Study 7 —— CSS美化背景和边框
  12. vision画流程图的软件_vision软件怎么画流程图
  13. Java SSM 商户管理系统 客户管理 库存管理 销售报表 项目源码
  14. python怎么输出roc曲线_如何用Python绘制ROC曲线
  15. samsung q1u android,奢华配置指纹科技 三星Q1U再造UMPC王者
  16. Time Limit Exceeded的原因及避免方法
  17. 设计模式——C++版
  18. Processing 案例 | 扑面而来的满天繁星
  19. WEEK 15 C ZJM 与纸条
  20. 05 -数据分析与SQL- Lesson5 SQL数据清理

热门文章

  1. Windows摄像头驱动研究(一)
  2. maven使用本地仓库作为远程仓库使用
  3. Python x-www-form-urlencoded post
  4. 2020年中国数字音乐用户“春节收听”内容洞察白皮书
  5. elsarticle模板 去掉摘要前后的两条横线
  6. 好想好想找个角落,自己躲起来,写自己的心情
  7. Redis存储java对象或者java对象数组
  8. 硕、博士论文致谢词产生器
  9. Python库资源大全
  10. Ubuntu删除文件夹的命令