题意:给出n和k ,求在n个数里每隔k个数求出其中的最小值和最大值并分别输出
思路:采用单调队列
单调队列的性质:
在动态规划的过程中,单调队列中每个元素一般存储的是两个值:
1、在原数列中的位置(下标)
2、在动态规划中的状态值
用一个数组模拟队列,记录下标
坑爹,我几乎调了两个小时,一直TLE,找位置改用二分法还是T了,最后想放弃了,然后用c++交A了!可怜我花了那么长时间
代码:
#include<iostream>
#include<cstdio>
using namespace std;
const int MAX = 1000001;
//两个单调队列
int dq1[MAX]; //存递减
int dq2[MAX]; //存递增
int a[MAX];
inline bool scan_d(int &num)
{
char in;
bool IsN=false;
in=getchar();
if(in==EOF)
return false;
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 true;
}
int main(void)
{
int i,n,k,front1,front2,tail1,tail2,start,ans;
while(scanf("%d %d",&n,&k)!=EOF)
{
for(i = 0 ; i < n ; ++i)
scan_d(a[i]);
front1 = 0, tail1 = -1;
front2 = 0, tail2 = -1;
ans = start = 0;
for(i = 0 ; i < k ; ++i)
{
while(front1 <= tail1 && a[ dq1[tail1] ] <= a[i])
--tail1;
dq1[ ++tail1 ] = i;
while(front2 <= tail2 && a[ dq2[tail2] ] >= a[i])
--tail2;
dq2[ ++tail2 ] = i;
}
//输出最小值
printf("%d ",a[ dq2[ front2 ] ]);
for( ; i < n ; ++i)
{
while(front2 <= tail2 && a[ dq2[tail2] ] >= a[i])
--tail2;
dq2[++tail2] = i;
while(dq2[ front2 ] <= i - k)
++front2;
if(i!= n-1)
printf("%d ",a[ dq2[ front2 ] ]);
}
printf("%d\n",a[dq2[ front2 ]]);
//输出最大值
printf("%d ",a[dq1[ front1 ]]);
for(i=k ; i < n ; ++i)
{
while(front1 <= tail1 && a[ dq1[tail1] ] <= a[i])
--tail1;
dq1[ ++tail1 ] = i;
while(dq1[ front1 ] <= i - k)
++front1;
if(i != n-1)
printf("%d ",a[ dq1[ front1 ] ]);
}
printf("%d\n",a[ dq1[ front1 ] ]);
}
return 0;
}

本文介绍使用单调队列解决滑动窗口内的最大值与最小值问题的方法,通过维护两个单调队列实现高效查找,适用于动态更新的数据序列。
257

被折叠的 条评论
为什么被折叠?



