A - 滑动窗口 /【模板】单调队列 洛谷 - P1886

Description

有一个长为 n 的序列 a,以及一个大小为 k 的窗口。现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值。

例如,对于序列 [1,3,−1,−3,5,3,6,7][1,3,−1,−3,5,3,6,7] 以及 k=3,有如下过程:

窗口位置最小值最大值

Input

输入一共有两行,第一行有两个正整数 n,k。
第二行 n 个整数,表示序列 a

Output

输出共两行,第一行为每次窗口滑动的最小值
第二行为每次窗口滑动的最大值

Sample 1

InputcopyOutputcopy
8 3
1 3 -1 -3 5 3 6 7
-1 -3 -3 -3 3 3
3 3 5 5 6 7

Hint

【数据范围】
对于 50%50% 的数据,1≤n≤10^5;
对于 100%100% 的数据,1≤k≤n≤10^6,ai​∈[−2^31,2^31)。

 

#include<iostream> // 引入标准输入输出库
using namespace std; // 使用标准命名空间
const int N=1000010; // 定义常量 N,表示数组的最大长度

int a[N],q[N]; // 定义两个全局数组 a 和 q

int main() { // 程序入口函数
	int n,k; // 定义变量 n 和 k,分别表示数组大小和滑动窗口大小
	scanf("%d%d",&n,&k); // 从标准输入读取 n 和 k 的值
	for(int i=0; i<n; i++) { // 循环读取数组 a 的每个元素
		scanf("%d",&a[i]);
	}
	int hh=0,tt=-1; // 初始化队列的头部和尾部指针
	for(int i=0; i<n; i++) { // 第一个循环,寻找最小值
		if(hh<=tt && i-q[hh]>k-1) { // 如果队列头部的元素已经不在窗口内,出队
			hh++;
		}
		while(hh<=tt&&a[q[tt]]>=a[i]) //  while 循环,确保队列的单调性
			tt--; // 如果队列尾部的元素大于等于新元素,出队
		q[++tt]=i; // 将新元素的下标加入队列尾部
		if(i>=k-1) // 如果当前位置 i 大于等于 k-1,输出队列头部的元素
			printf("%d ",a[q[hh]]);
	}
	puts(""); // 输出一个换行符
	hh=0,tt=-1; // 重置队列的头部和尾部指针
	for(int i=0; i<n; i++) { // 第二个循环,寻找最大值
		if(hh<=tt && i-q[hh]>k-1) { // 如果队列头部的元素已经不在窗口内,出队
			hh++;
		}
		while(hh<=tt&&a[q[tt]]<=a[i]) // while 循环,确保队列的单调性
			tt--; // 如果队列尾部的元素小于等于新元素,出队
		q[++tt]=i; // 将新元素的下标加入队列尾部
		if(i>=k-1) // 如果当前位置 i 大于等于 k-1,输出队列头部的元素
			printf("%d ",a[q[hh]]);
	}
	puts(""); // 输出一个换行符
}

这段代码是用来实现滑动窗口中的最大值和最小值的问题。下面是代码的解析思路:

  1. 引入标准输入输出库,并使用标准命名空间。
  2. 定义常量 N,表示数组的最大长度。
  3. 定义两个全局数组 a 和 q,其中 a 用来存储数组的元素,q 用来存储滑动窗口中的下标。
  4. 程序入口函数 main()。
  5. 从标准输入读取 n 和 k 的值,分别表示数组大小和滑动窗口大小。
  6. 使用循环读取数组 a 的每个元素,并存储到 a 数组中。
  7. 初始化队列的头部指针 hh 和尾部指针 tt,其中 hh = 0,tt = -1。
  8. 第一个循环用来寻找最小值,其中 i 表示当前遍历的位置。
  9. 如果队列头部的元素已经不在窗口内,即 i - q[hh] > k-1,队列头部元素出队。
  10. 使用 while 循环,确保队列的单调性,即队列中的元素按照递增顺序排列。
  11. 如果队列尾部的元素大于等于新元素 a[i],则队尾元素出队。
  12. 将新元素的下标 i 加入队列尾部。
  13. 如果当前位置 i 大于等于 k-1,输出队列头部的元素 a[q[hh]],即当前窗口的最小值。
  14. 第一个循环结束后,输出一个换行符。
  15. 重置队列的头部和尾部指针,即 hh = 0,tt = -1。
  16. 第二个循环用来寻找最大值,逻辑与第一个循环类似。
  17. 最后输出一个换行符。
  • 11
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值