首页 > 其他分享 >浅谈单调队列

浅谈单调队列

时间:2022-10-06 16:57:30浏览次数:81  
标签:浅谈 队列 sum front 端点 序列 单调

单调队列,顾名思义就是一个元素之间的关系具有单调性的队列

我们通过一道例题来讲解

最大子序和

题目大意

给定一个长度为 \(N\) 的整数序列(可能有负数),从中找出一段长度不超过 \(M\) 的连续子序列,使得子序列中所有数的和最大。 $N,M \le 3 \cdot 10^5 $。

solution

计算“区间和”的问题,一般转化为“两个前缀和相减”的形式进行求解。我们先求出 \(S[i]\) 表示序列里前 \(i\) 项的和,则连续子序列 \([L,R]\) 中的数的和就等于 \(S[R] - S[L-1]\)。那么原问题就可以转化为:

找出两个位置 \(x,y\) 使 \(S[y] - S[x]\) 最大并且 \(y - x \le M\)。

首先我们枚举右端点 \(i\),当 \(i\) 固定时,问题就变为:

找到一个左端点 \(j\),其中 \(j \in [i-m,i-1]\) 并且 \(S[j]\) 最小。

不妨比较一下任意两个位置 \(j\) 和 \(k\),

如果 \(k<j<i\) 并且 \(S[k] \ge S[j]\),

那么对于所有大于等于 \(i\) 的右端点,\(k\) 永远不会成最优选择。

这是因为不但 \(S[k] \not < S[j]\),而且 \(j\) 离 \(i\) 更近,长度更不容易超过 \(M\),即 \(j\) 的生存能力比 \(k\) 更强。所以当 \(j\) 出现后,\(k\) 就完全是一个无用的位置。

以上比较告诉我们,可能成为最优选择的策集合一定是一个

“下标位置递增、对应的前缀和S的值也递增” 的序列。

我们可以用一个队列保存这个序列。随着右端点位置改变,从前向后扫描,我们对每个 \(i\) 执行以下三个步骤:

  1. 判断队头决策与 \(i\) 的距离是否超出 \(M\) 的范围,若超出则出队。
  2. 此时队头就是右端点为 \(i\) 时,左端点 \(j\) 的最优选择。
  3. 不断删除队尾决策,直到队尾对应的S值小于 \(S[i]\)。然后把 \(i\) 作为一个新的决策入队。

实现方法:STL双端队列 或 手写(此处只展示了双端队列代码)

deque<int> q;
while(q.size()) q.pop_front();
q.push_back(0);
for(int i=1;i<=n;i++){
	while(q.size()&&i-q.front()>k) q.pop_front();
	ans=max(ans,sum[i]-sum[q.front()]);
	while(q.size()&&sum[q.front()]>=sum[i]) q.pop_back();
	q.push_back(i);
}

这就是著名的单调队列算法,因为每个元素至多入队一次、出队一次,所以整个算法的时间复杂度为 \(O(N)\)。

它的思想也是 在决策集合(队列)中及时排除一定不是最优解的选择。 单调队列也是优化动态规划的一个重要手段。

练习题

滑动窗口 /【模板】单调队列

coding

标签:浅谈,队列,sum,front,端点,序列,单调
From: https://www.cnblogs.com/ycw123/p/16757950.html

相关文章

  • 消息队列 基础概念
    消息队列基本概念什么是消息队列异步通讯的中间件:存放消息的容器。当我们需要使用消息时,取出消息供我们使用。消息是一种数据结构(当然,对象也可以看做是一种特殊的消......
  • 算法竞赛备赛之浅谈递归
    递归递归需要有基例、递归前进段和递归返回段(return语句),是一种程序设计技巧,可以使程序编写简单,但实际上要付出低效率的代价计算时间复杂度常用数据的记忆(程序设计基本功,......
  • 浅谈树链剖分
    树链剖分是把一棵树分割成若干条链,以便于维护信息的一种方法,其中最常用的是重链剖分(HeavyPathDecomposition,重路径分解),所以一般提到树链剖分或树剖都是指重链剖分。除此......
  • STL优先队列
    STL大法好STL优先队列就是一个封装的堆,学会熟练运用,免去手写堆的麻烦其实是不会自己写格式:priority_queue<类型,vector<类型>,比较类>q;优先队列的源码比较奇特......
  • 单调栈理解
    单调栈个人理解总结:1.单调栈是用来解决这一类问题:寻找数组中元素其左或者右第一个大于或小于该元素的值。2.首先,如果要寻找其右侧,要从右向左遍历。反之,从左向右遍历。3.......
  • POJ 3494 Largest Submatrix of All 1’s(单调栈)
    POJ3494LargestSubmatrixofAll1’s(单调栈)题意:​ 给出一个01矩阵,请找出其中最大的全部为1构成的子矩阵。矩阵大小为\(2000*2000\)思路:​ 我们把问题分解到每一......
  • 代码随想录day11 | 232.用栈实现队列 225.队列实现栈 20.有效的括号 1047. 删除字符
    232.用栈实现队列题目|文章1.使用两个栈(修改输出)思路1.使用两个栈,用一个栈输入数据,用另一个栈输出数据2.当输出栈为空时,将输入栈的数据转移到输出栈中实现点击查看......
  • kafka 通过代码对队列进行操作
    StringbootstrapServers="192.163.0.1:9092";KafkaAdminkafkaAdmin;AdminClientadminClient;/***项目启动调用或者通过@Bean注入*/......
  • 21-RabbitMQ延迟队列插件
    RabbitMQ延迟队列插件下载官网https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases我用的是3.10.7的RabbitMQ,但是官网没有这么新版本的,只......
  • 16-RabbitMQ高级特性-消费端的消息ACK与重回队列
    消费端的消息ACK与重回队列消费端的手工ACK和NACKACK分为自动和手动消费端进行消费的时候,如果由于业务异常我们可以进行日志的记录,然后进行补偿如果由于服务器宕......