Sliding Window
http://www.acm.uestc.edu.cn/problem.php?pid=1221
本题运用单调队列解决。
由于需要输出最大值与最小值两个序列 ,于是需要维护两个分别是递增的和递减的单调队列。
建立一个队列数组,数组元素是一个结构体,结构体的id信息用于保存这个队列元素在原数组中的坐标(主要作用在于比较对头元素是否符合要求。我曾经想在队列中直接保存数值)但是苦于无法获得head的id,因为它时刻的变动。
首先将队列的首元素的id写成0,然后从1开始逐个加入逐个记录,维护递增队列的时候将逐个入队的元素与队尾的元素进行比较,如果大于队尾元素则替换队尾元素直到小于队尾元素,然后将其赋给队尾元素,再检查队头,如果对头元素与队尾元素之间的距离大于k,则head++,再将对头元素赋给相应位置的max[i]min[i].
注意输出的时候最后一个元素不能带空格。
#include<cstdio>
#define N 1000005
using namespace std;
struct node
{
int id;
};
node queue[N];
int s[N],max[N],min[N];
int a,k,tail,head;
//递减队列 求取最大值
void dec()
{
head = tail =0;
queue[tail++].id=0;
max[0] = s[0];
for(int i=1;i<a;i++)
{
while(s[queue[tail-1].id]<s[i]&&head<tail)
{
tail--;
}
queue[tail++].id =i;
//去除多余的对头元素
if(queue[head].id<i-k+1)
head++;
max[i] = s[queue[head].id];
}
}
//递增队列 求取最小值
void inc()
{
head = tail =0;
queue[tail++].id=0;
min[0] = s[0];
for(int i=1;i<a;i++)
{
while(s[queue[tail-1].id]>s[i]&&head<tail)
{
tail--;
}
queue[tail++].id =i;
//去除多余的对头元素
if(queue[head].id<i-k+1)
head++;
min[i] = s[queue[head].id];
}
}
int main()
{
//freopen("1.txt","r",stdin);
while(scanf("%d%d",&a,&k)==2)
{
int i;
for(i=0;i<a;i++)
scanf("%d",&s[i]);
dec();
inc();
for(i=k-1;i<a-1;i++)
printf("%d ",min[i]);
printf("%d\n",min[i]);
for(i=k-1;i<a-1;i++)
printf("%d ",max[i]);
printf("%d",max[i]);
}
return 0;
}
如果采用暴力的解法解答这个题目的话,就会出现超时。
显然这个题目如果暴力的话需要O(n^2)的时间复杂度(两个for循环)