题意:给出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;
}