这是一道单调队列的题目,做这道题目也是为了理解单调队列到底是什么东西,下面是摘自百度百科的一段说明,说的明不明白呢,只可意会不可言传~
单调队列查询为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;
}