先分析一下单调队列的题,要不然都快忘光了。

题目大意:给你一串长度为n的数组,一扇长度为k的窗从最左端滑动到最右端,每次滑动如下表

求每次滑动的min.value 和 max.value.

输入格式

第 1 行 n,k, 第 2 行为长度为 n 的数组

输出格式

2 行, 第 1 行每个位置的 min value, 第 2 行每个位置的 max value

样例数据

input

8 3 
1 3 -1 -3 5 3 6 7

output

-1 -3 -3 -3 3 3 
3 3 5 5 6 7

数据规模与约定

20%: n<=500;  

50%: n<=100000;

100%: n<=1000000;

时间限制:1s1s

空间限制:256MB256MB


主要思路:控制窗户移动,选出每次移动的最小值,存入数列中,把比自己大或小的挤出队列(找大的挤小的,找小的挤大的),并且保证队首是我们要求的值,分两部分分别求最大最小。代码如下:

#include<bits/stdc++.h>
using namespace std;
int n,k,a[1000010],q[1000010],head=1,tail;
int main()
{
scanf("%d%d",&n,&k);//n个数,k长度的查询 
for (int i=1;i<=n;++i)
scanf("%d",&a[i]);//读入n个数 

for (int i=1;i<=n;++i)//先处理最小值 
{
if (i-q[head]>=k) head++;//当超过k的时候,计算下一组m个数。 控制窗户移动 
while (a[i]<a[q[tail]]&&head<=tail)//目的让最小的值留在队首。当元素小于队尾的数,队尾的数出栈,队尾指针减减。 
tail--;
q[++tail]=i;//否则的话,当前元素进队,队尾指针加加 
if (i>=k)
{
if (i==n) cout<<a[q[head]]<<endl;
else cout<<a[q[head]]<<" "; //输出队首元素,处理最后一个元素的输出。 
}
}

memset(q,0,sizeof(q));
head=1;
tail=0;
for (int i=1;i<=n;++i)
{
if (i-q[head]>=k) head++;
while (a[i]>a[q[tail]]&&head<=tail)//同上,目的让最大的值留在队首。当元素大于队尾的数,队尾的数出栈,队尾指针减减。  
tail--;
q[++tail]=i;
if (i>=k)
{
if (i==n) cout<<a[q[head]]<<endl;
else cout<<a[q[head]]<<" ";
}
}
return 0;
}

注:输出时空格的输出千万注意,否则等待你的将是0分~

另,附一图供大家一观:


(全是题目哦~)

猜你喜欢

转载自blog.csdn.net/smileyx2005/article/details/79067651