洛谷:P1440 求m区间内的最小值(彻底掌握单调队列)

一、题目

题目传送门:P1440 求m区间内的最小值 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/problem/P1440

题目描述

洛谷:P1440 求m区间内的最小值(彻底掌握单调队列)_第1张图片

二、题解

1.本题难点

        本题用暴力解法时间复杂度为O(n*m)

        所以我们就可以考虑用单调队列优化时间复杂度为O(n)

        下面我们来了解什么是单调队列:

单调队列,顾名思义,是一种具有单调性的队列。众所周知,单调性有单调递增和单调递减两种,相应的单调队列也分为单调递增队列和单调递减队列两种。

  • 单调递增队列:保证队列头元素一定是当前队列的最小值,用于维护区间的最小值。

  • 单调递减队列:保证队列头元素一定是当前队列的最大值,用于维护区间的最大值。

 实现流程:

实现单调队列,主要分为三个部分:

  • 去尾操作队尾元素出队列。当队列有新元素待入队,需要从队尾开始,删除影响队列单调性的元素,维护队列的单调性。(删除一个队尾元素后,就重新判断新的队尾元素)

去尾操作结束后,将该新元素入队列。

  • 删头操作队头元素出队列。判断队头元素是否在待求解的区间之内,如果不在,就将其删除。(这个很好理解呀,因为单调队列的队头元素就是待求解区间的极值)

  • 取解操作 :经过上面两个操作,取出 队列的头元素 ,就是 当前区间的极值

2.本题注意事项

1.数据量大的时候,用cout输出的时候千万别和endl一起,如果我们的算法思路一致,可能就是用了cout<

具体原因你试试就知道,本题用cout<

传送门:std::endl为什么导致程序变慢 – 胡超博客 (imhuchao.com)

 定义两个超大数组时改用全局变量,不然你的编译器可能运行出错

3.过程讲解

1)定义两个数组,一个数组q[n]用来作为一个简单队列,一个数组a[n]用来接收传进来的元素,记得将数组最大化,确保数据量大的时候全部能存取。q[n]队列里存的是数组的下标,访问元素可以用a[q[n]]来访为第n个元素。

2)因为第一元素的前没有前m项,所以直接输出0

3)写一个单调队列

4.代码

#include 
using namespace std;
int q[2000005], a[2000005];
int main()
{
	
	int m, k, front = 1, rear = 0;
	cin >> m >> k;

	for (int i = 1; i <= m; i++)
		cin >> a[i];
	cout << 0 << endl;
	for (int i = 1; i <= m - 1; i++) //构建单调队列
	{
	while (front <= rear &&q[front] <= i - k) //保证队首在前m区间内
			front++;
	while (front <= rear && a[q[rear]] >= a[i])//维护一个单调递增队列
			rear--;
		q[++rear] = i;   //入队
		cout<

5.附上结果

洛谷:P1440 求m区间内的最小值(彻底掌握单调队列)_第2张图片

你可能感兴趣的:(算法,c++,数据结构,推荐算法)