【单调队列】Sliding Window(C++)

描述

【单调队列】Sliding Window(C++)_第1张图片
给你n个数,求每部分连续的m个数里面的最大值最小值。
http://poj.org/problem?id=2823

输入

The input consists of two lines. The first line contains two integers n and k which are the lengths of the array and the sliding window. There are n integers in the second line.

输出

There are two lines in the output. The first line gives the minimum values in the window at each position, from left to right, respectively. The second line gives the maximum values.

样例

输入

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

输出

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





这个题可以用单调队列来做,并且这是个模板题。
这个题有两部分,最大值和最小值,其实你会一种就行了,因为另一种改个符号即可!
代码:

#include
using namespace std;
int n,k,a[1000001],id[1000001],dl[1000001],l=1,r;
//a数组代表每个点的数值
//id代表每个数的下标
//dl代表队列 
int main() {
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++)
	scanf("%d",&a[i]);
	for(int i=1;i<=n;i++)
	{
		while(l<=r&&a[i]<=dl[r])    //如果左端点小于右端点,且将要加入的数小于队尾的数,就将其删去 
		r--;    //不需要将那个数进行什么操作,只需要移动一下端点就可以实现删掉那个数的操作 
		r++;
		dl[r]=a[i];    //加入队列 
		id[r]=i;    //记上这个数的下标 
		if(id[l]+k<=i)    //如果这个数下标太大了 
		l++;    //移动一下 
		if(i>=k)
		cout<<dl[l]<<" ";   //符合条件,输出! 
	}
	cout<<endl; 
	memset(dl,0,sizeof(dl));//初始化 
	memset(id,0,sizeof(id));
	l=1,r=0;
	for(int i=1;i<=n;i++)
	{
		while(l<=r&&a[i]/*后面这个大于号改一下就行了,后面不要动*/>=dl[r])
		r--;
		r++;
		dl[r]=a[i];
		id[r]=i;
		if(id[l]+k<=i)
		l++;
		if(i>=k)
		cout<<dl[l]<<" ";
	}
	cout<<endl;

	return 0;
}

你可能感兴趣的:(Mushroom,OJ,Poj)