poj2823 Sliding Window

单调队列
(题面:http://poj.org/problem?id=2823)
题意就是给一堆数和一个窗口,求窗口滑到某一位置时里面的最小值最大值
于是乎我们有了单调队列做法
这题用STL的双端队列貌似会RE,自己写一个就好了
我们以最小值为例:
8 3
1 3 -1 -3 5 6 7 8(注意和题面中数据不太一样)
维护两个deque,其中一个存值(我们用英文字母q表示),另一个存下标(我们用英文字母p表示)
(1)1号元素"1"入队,q={1},p={1}
(2)2号元素"3"入队,此时"3"发现他前面有个"1",但是他毫无顾忌,因为如果窗口左边界过了1而后边的数都比他大的话,他有可能是最小值的,所以把"3"入队,q={1,3},p={1,2}
(3)3号元素"-1"入队,此时"-1"发现他前面有个"3",而"-1"是在"3"的后面被加入的,所以只要"3"没有出窗口,"-1"肯定不会出窗口,"-1"<"3",所以我们要把"3"舍弃,"3"从末尾出队,此时"-1"又发现前面有个"1",同理"1"也从末尾出队,"-1"入队,此时q={-1},p={3},发现已经找过了3个元素,从今以后可以输出了,此时输出"-1"为[1,3]的最小值
(4)4号元素"-3"入队,同上我们要把"-1"从末尾出队,"-3"入队,所以q={-3},p={4},输出"-3"为[2,4]的最小值
(5)5号元素"5"入队,根据(2)中的解释,他也可能成为最小值的,将5从末尾入队q={-3,5},p={4,5}输出"-3"为[3,5]的最小值
(6)6号元素"6"入队,此时q={-3,5,6},p={4,5,6},输出"-3"为[4,6]的最小值
(7)7号元素"7"入队,此时q={-3,5,6,7},p={4,5,6,7},输出"-3"为[5,7]的最小值,哎不对,"-3"不是4号元素吗,现在已经过时了,这时候我们应该判断一下队首元素序号+k是否大于i,不是的话弹出,所以这时候我们要把"-3"从队首弹出队列,此时q={5,6,7},p={5,6,7},输出"5"为[5,7]的最小值
(8)8号元素"8"入队,此时队首的5号元素也该出队了,q={6,7,8},p={6,7,8},输出"6"作为[6,8]的最小值
所以答案为-1 -3 -3 -3 5 6
然后一定要把队列清空了,再跑最大值,最大值就是比较的时候把小于号改成大于号即可
码子:

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;

struct deque
{int aa[1000010];
	int head,tail;
	deque(){head=1;tail=1;}//[head,tail)
	bool empty(){return head==tail;}
	void push_back(int x){aa[tail++]=x;}
	void pop_back(){tail--;}
	void pop_front(){head++;}
	int back(){return aa[tail-1];}
	int front(){return aa[head];}
	void clear(){memset(aa,0,sizeof(aa));head=tail=1;}
}p,q;
int n,k,a[1000010];
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(!q.empty()&&q.back()>a[i])
		{
			q.pop_back();
			p.pop_back();
		}
		if(!p.empty()&&p.front()+k<=i)
		{
			q.pop_front();
			p.pop_front();
		}
		q.push_back(a[i]);
		p.push_back(i);
		if(i>=k)printf("%d%c",q.front(),i==n?'\n':' ');
	}
	q.clear();
	p.clear();
	for(int i=1;i<=n;i++)
	{
		while(!q.empty()&&q.back()<a[i])
		{
			q.pop_back();
			p.pop_back();
		}
		if(!p.empty()&&p.front()+k<=i)
		{
			q.pop_front();
			p.pop_front();
		}
		q.push_back(a[i]);
		p.push_back(i);
		if(i>=k)printf("%d%c",q.front(),i==n?'\n':' ');
	}
	return 0;
}
posted @ 2018-04-04 11:05  ghj1222  阅读(141)  评论(0编辑  收藏  举报