洛谷 P1886 滑动窗口

题目描述

现在有一堆数字共$N$个数字($N<=10^6$),以及一个大小为$k$的窗口。现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值。

例如:

The array is [1 3 -1 -3 5 3 6 7], and $k = 3$.

输入输出格式

输入格式:

输入一共有两行,第一行为$n,k$。

第二行为$n$个数(<INT_MAX).

输出格式:

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

第二行为每次窗口滑动的最大值

输入输出样例

输入样例#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%的数据,$n<=10^5$

100%的数据,$n<=10^6$

题解

单调队列の模板题

然后。。。。就这样辣?

注意维护队首和插入队尾就可以了

#include <map>
#include <list>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
//#pragma GCC optimize(2)
#define endl '
'
#define fast ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;
int n,m;
int q1[1000005],q2[1000005];
int a[1000005];

inline int read() //快读
{
    int x=0,f=1;char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x*=10;x+=(ch-'0');ch=getchar();}
    return x*f;
}

int min_deque()
{
	int L=1,r=0;
	
	for (register int i=1;i<=n;i++)
	{
		while (L<=r && q1[L]+m<=i)
		   L++;
		while(L<=r && a[i]<a[q1[r]])
		   r--;
		q1[++r]=i;
		if (i>=m)
		   cout<<a[q1[L]]<<" ";
	}
	cout<<endl;
}

int max_deque()
{
	int L=1,r=0;
	
	for (register int i=1;i<=n;i++)
	{
		while (L<=r && q2[L]+m<=i)
		   L++;
		
		while (L<=r && a[i]>a[q2[r]])
		   r--;
		q2[++r]=i;
		if (i>=m)
		   cout<<a[q2[L]]<<" ";
	}
}

int main()
{
	fast;
	cin>>n>>m;
	for (register int i=1;i<=n;i++)
	   a[i]=read();
	min_deque();
	max_deque();
	return 0;
}

  

$Think;twice,code;once.$
原文地址:https://www.cnblogs.com/ttyclear/p/9276604.html