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


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



时间限制 1.00s
内存限制 125.00MB


题目描述


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

例如:

The array is \([1,3,−1,−3,5,3,6,7]\), and \(k=3\)


输入格式


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


输出格式


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


输入输出样例


输入 #1

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

输出 #1

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

说明/提示


【数据范围】
对于\(50\%\)的数据,\(1 \le n \le 10^5\)
对于\(100\%\)的数据,\(1\le k \le n \le 10^6\)\(a_i \in [-2^{31},2^{31})\)



代码


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=1e6+5;
int ansmn[N],ansmx[N];
struct node{ int v,t; };
deque<node>qmx,qmn;
int main(){
	int n,k;
	scanf("%d %d",&n,&k);
	for(int x,i=1;i<=n;++i){
		scanf("%d",&x);
		if(!qmx.empty()&&qmx.front().t<(i-k+1)) qmx.pop_front();
		if(!qmn.empty()&&qmn.front().t<(i-k+1)) qmn.pop_front();
		while(!qmx.empty()&&x>qmx.back().v) qmx.pop_back();
		qmx.push_back(node{x,i});
		while(!qmn.empty()&&x<qmn.back().v) qmn.pop_back();
		qmn.push_back(node{x,i});
		if(i>=k){
			ansmx[i-k+1]=qmx.front().v;
			ansmn[i-k+1]=qmn.front().v;
		}
	}
	for(int i=1;i<=n-k+1;++i) printf("%d ",ansmn[i]);
	puts("");
	for(int i=1;i<=n-k+1;++i) printf("%d ",ansmx[i]);
	return 0;
}
原文地址:https://www.cnblogs.com/Potrem/p/Luogu_P1886.html