【刷题】数据结构——单调队列【模板】:滑动窗口

在这里插入图片描述题目链接

用长度k的队列来维护窗口。

先考虑求窗口的最小值,窗口内有数字 a [ i ] a[i] a[i]
不妨设 a [ i ] a[i] a[i]左边的比它大的数是 a [ j ] a[j] a[j],因为 a [ j ] a[j] a[j]会比 a [ i ] a[i] a[i]先出窗口,那么 a [ i ] a[i] a[i]在的时候窗口最小值不可能是 a [ j ] a[j] a[j]

因此只要保留 a [ i ] a[i] a[i] a [ i ] a[i] a[i]左边比它小的数即可,左边比它大的数可以去掉。
这样队列就是从小到大的单调队列。

具体操作就是 a [ i ] a[i] a[i]从队尾进队时,从队尾向队头扫描,找到第一个比 a [ i ] a[i] a[i]小的数,将 a [ i ] a[i] a[i]放在这个数后面当新的队尾。
窗口最小值就是队头。

同理,求窗口最大值,队列就是从大到小的单调队列。

#include <iostream>
using namespace std;

const int N = 1000005;
int n, k, a[N];
int q1[N], q2[N], h1, t1, h2, t2; // 队列存的是a数组下标 
int ans1[N], ans2[N];
int main() {
	
	scanf("%d%d", &n, &k);
	h1 = 0, t1 = -1;
	h2 = 0, t2 = -1;
	for (int i = 1; i <= n; i ++ ) {
		scanf("%d", &a[i]);
		if (h1 <= t1 && i - k >= q1[h1]) h1 ++ ; // 窗口右移,弹出队头 
		while(h1 <= t1 && a[i] <= a[q1[t1]]) t1 -- ;
		q1[ ++ t1] = i;
		if (i >= k) ans1[i - k + 1] = a[q1[h1]];
		
		if (h2 <= t2 && i - k >= q2[h2]) h2 ++ ; // 窗口右移,弹出队头 
		while (h2 <= t2 && a[i] >= a[q2[t2]]) t2 -- ;
		q2[ ++ t2] = i;
		if (i >= k) ans2[i - k + 1] = a[q2[h2]];
	}
	for (int i = 1; i <= n - k + 1; i ++) {
		printf("%d ", ans1[i]);
	}
	printf("\n");
	for (int i = 1; i <= n - k + 1; i ++) {
		printf("%d ", ans2[i]);
	}
	printf("\n");
	
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值