zoukankan      html  css  js  c++  java
  • 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?'
    ':' ');
    	}
    	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?'
    ':' ');
    	}
    	return 0;
    }
    
  • 相关阅读:
    jsp 特殊标签
    poj 1753 Flip Game 高斯消元 异或方程组 求最值
    zoj 3155 Street Lamp 高斯消元 异或方程组 求方案数
    poj1222 EXTENDED LIGHTS OUT 高斯消元解异或方程组 模板
    zoj 3930 Dice Notation 模拟
    zoj 3157 Weapon 线段树求逆序对数
    hdu 1242 Rescue BFS+优先队列
    hdu 3466 Proud Merchants 贪心+01背包
    zoj 3689 Digging 贪心+01背包
    hdu 2602 Bone Collector 01背包模板
  • 原文地址:https://www.cnblogs.com/oier/p/8716031.html
Copyright © 2011-2022 走看看