POJ 2823 Sliding Window

来源:互联网 发布:手机淘宝卖家软件 编辑:程序博客网 时间:2024/05/17 02:49

这是一道单调队列的题目,做这道题目也是为了理解单调队列到底是什么东西,下面是摘自百度百科的一段说明,说的明不明白呢,只可意会不可言传~

单调队列查询为O(1)。

进队出队稍微复杂点:
进队时,将进队的元素为e,从队尾往前扫描,直到找到一个不大于e的元素d,将e放在d之后,舍弃e之后的所有元素;如果没有找到这样一个d,则将e放在队头(此时队列里只有这一个元素)。
出队时,将出队的元素为e,从队头向后扫描,直到找到一个元素f比e后进队,舍弃f之前所有的。(实际操作中,由于是按序逐个出队,所以每次只需要出队只需要比较队头)。
每个元素最多进队一次,出队一次,摊排分析下来仍然是 O(1)。
上面的话可能还是没能讲出单调队列的核心:队列并不实际存在的,实际存在的是具有单调性的子序列。对这个子序列按心中的队列进行操作,譬如在进队时丢弃的元素,虽然它不存在于这个子序列里,但是还是认为他存在于队列里


在这个题中,我们建立两个分别递增和递减的队列increase和decrease。以increase队列为例,当输入一个新的元素时,从队尾开始寻找,如果队尾元素大于num是把队尾元素删除,直到第一个不大于它的元素,在该元素后插入。另外对距离大于k的元素要从队列中删除。

代码如下,在提交我已经用了input挂居然还是过不了poj的G++,后来改C++一下就过了,看来优化还不够啊



#include <iostream>#include <cstdio>using namespace std;const int M = 1000005;struct Node{int m,d;}increase[M],decrease[M];int num,mi[M],ma[M];int head_in,tail_in,head_de,tail_de,top;int input(){char in;bool isn = false;int num;in = getchar();while(in != '-' && (in < '0'||in > '9'))in = getchar();if(in == '-'){ isn = true;num = 0;}else num = in - '0';while(in = getchar(),in >= '0' && in <= '9'){num *= 10;num += in - '0';}if(isn) num = -num;return num;}int main(){int n,k;scanf("%d%d",&n,&k);head_in = tail_in = head_de = tail_de = top = 0;//scanf("%d",&num);num = input();increase[0].m = decrease[0].m = num;increase[0].d = decrease[0].d = 0;for(int i = 1;i < k;i++){//scanf("%d",&num);num = input();while(increase[tail_in].m > num && tail_in >= head_in) tail_in--;tail_in++;increase[tail_in].d = i;increase[tail_in].m = num;while(decrease[tail_de].m < num && tail_de >= head_de) tail_de--;tail_de++;decrease[tail_de].d = i;decrease[tail_de].m = num;}mi[top] = increase[head_in].m;ma[top++] = decrease[head_de].m;for(int i = k;i < n;i++){//scanf("%d",&num);num = input();while(increase[tail_in].m > num && tail_in >= head_in) tail_in--;tail_in++;increase[tail_in].d = i;increase[tail_in].m = num;while(i - increase[head_in].d + 1 > k)head_in++;while(decrease[tail_de].m < num && tail_de >= head_de) tail_de--;tail_de++;decrease[tail_de].d = i;decrease[tail_de].m = num;while(i - decrease[head_de].d + 1 > k)head_de++;mi[top] = increase[head_in].m;ma[top++] = decrease[head_de].m;}for(int i = 0;i < top-1;i++)printf("%d ",mi[i]);printf("%d\n",mi[top-1]);for(int i = 0;i < top-1;i++)printf("%d ",ma[i]);printf("%d\n",ma[top-1]);return 0;}


原创粉丝点击