如果当初看单调队列先从这题开始做的话,应该会快点理解吧。
题意就是求区间最值,这是单调队列最简单的应用。
题意:
给你n个数和区间长度k,求区间遍历到第i个数时的最小和最大值,所以是n-k+1个值。
由于n的范围是10^6,普通嵌套for肯定超时,这里就用到了单调队列。
单调队列只需要遍历一遍,虽然中间有出队入队的操作
具体的看代码和注释吧:
#include <stdio.h>
#include <deque>
using namespace std;
int max_num[1000005],min_num[1000005],num[1000005];
int main()
{
int n,k;
while(scanf("%d %d",&n,&k)!=EOF)
{
deque<int > qmax,qmin;//单调队列记录下标
for(int i=1;i<=k-1;i++) //先输入前k-1个数,同时维护单调队列
{
scanf("%d",&num[i]);
while(!qmax.empty() && num[qmax.back()]<num[i]) qmax.pop_back();
while(!qmin.empty() && num[qmin.back()]>num[i]) qmin.pop_back();
qmax.push_back(i);
qmin.push_back(i);
}
for(int i=k;i<=n;i++) //从第k个数开始求区间最值
{
scanf("%d",&num[i]);
while(!qmax.empty() && num[qmax.back()]<num[i]) qmax.pop_back();//同上,维护单调队列
while(!qmin.empty() && num[qmin.back()]>num[i]) qmin.pop_back();
qmax.push_back(i);
qmin.push_back(i);
while(!qmax.empty() && i-qmax.front()>=k) qmax.pop_front(); //如果区间长度大于k,队头元素出队
while(!qmin.empty() && i-qmin.front()>=k) qmin.pop_front();
max_num[i-k+1]=num[qmax.front()]; //记录第i个最大值
min_num[i-k+1]=num[qmin.front()]; //记录第i个最小值
}
for(int i=1;i<=n-k;i++) //输出
printf("%d ",min_num[i]);
printf("%d\n",min_num[n-k+1]);
for(int i=1;i<=n-k;i++)
printf("%d ",max_num[i]);
printf("%d\n",max_num[n-k+1]);
}
return 0;
}