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。
在這裏插入圖片描述

輸入格式
輸入一共有兩行,第一行有兩個正整數 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<cstdio>
#include<deque>
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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章