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

【洛谷P1886】滑动窗口【单调队列】
题目描述
有一个长为 nn 的序列 aa,以及一个大小为 kk 的窗口。现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值。

例如:

The array is [1,3,-1,-3,5,3,6,7][1,3,−1,−3,5,3,6,7], and k = 3k=3。
P1886 滑动窗口 /【模板】单调队列_第1张图片

输入格式
输入一共有两行,第一行有两个正整数 n,kn,k。 第二行 nn 个整数,表示序列 aa

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

输入

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

输出

-1 -3 -3 -3 3 3
3 3 5 5 6 7

开始一直把优先队列和单调队列混淆,学习完单调队列才发现两者并不一样。
单调队列是维护一个递增或递减的序列。以题目输出k区间的最小值为例,q是被维护的deque:
1.输入1,q[1];
2.输入3,3有可能是别的区间的最小值,q[1,3];
3,输入-1,因为队尾是3,而3>-1,有-1的存在3就不可能是某个区间的最小值,所以抛出3,同理抛出1,q[-1],输出-1;
4.输入-3,-1>-3抛出-1,输出-3;
5.输入5,q[-3,5],输出-3;
6.输入3,3>5,抛出5,q[-3,3],输出-3;
7.输入6,-3不在k区间内了,抛出-3,q[3,6],输出3;
8.输入7,q[3,6,7],输出3。

#include
#include
using namespace std;
const int N=1e6+10;
int a[N],a1[N],a2[N];
deque<int>q1;
deque<int>q2;
int main()
{
	int n,k,i,j;
	scanf("%d %d",&n,&k);
	for(i=1;i<=n;i++){
		scanf("%d",&a[i]);
		while(q1.size()&&a[q1.back()]>a[i]) q1.pop_back();
		while(q2.size()&&a[q2.back()]<a[i]) q2.pop_back();
		q1.push_back(i);
		q2.push_back(i);
		if(i>=k){
			while(i-k>=q1.front()) q1.pop_front();
			while(i-k>=q2.front()) q2.pop_front();
			a1[i]=a[q1.front()];
			a2[i]=a[q2.front()];
		}
	}
	for(i=k;i<=n;i++)
		printf("%d ",a1[i]);
	printf("\n");
	for(i=k;i<=n;i++)
		printf("%d ",a2[i]);
	printf("\n");
	return 0;
}

你可能感兴趣的:(洛谷,数据结构,算法)