http://poj.org/problem?id=2823
模拟
n=8 k=3
1 3 -1 -3 5 3 6 7
先求最大值,用单调递减队列,输出队头
head=1,这样q[head]就直接是队首元素下标了
h=1 t=0
i=1 1 空队列,1入队 h=1 t=1
i=2 3 1<3出队 h=1 t=1
i=3 3 -1 3>-1,-1入队 i>=k,输出队头3
i=4 3 -1 -3 -1>-3,-3入队 i>=k,输出队头3
i=5 5 3的下标为2,i-2>=k,3出队 -3<5,-3出队,-1<5,-1出队 i>=k,输出队头5
i=6 5 3 5>3,3入队,输出队头5
i=7 6 3<6,3出队,5<6,5出队 输出队头6
i=8 7 6<7,6出队 输出队头7
3 3 5 5 6 7
#include<cstdio>
#include<iostream>
using namespace std;
const int N=1e6+1;
int n,k,a[N],q[N];//a存放数据,q存放下标
int head=1,tail;//head<tail时队列非空 令head=1是因为这样的话q[head]就是队首元素下标了,否则head需要加一
int main(){
scanf("%d%d",&n,&k);
//求最小值,用递增序列,输出队尾
head=1,tail=0;
for(int i=1;i<=n;i++)
{
scanf("%d",a+i);
//入队前先维护队列,head<=tail则队列非空
//改变队头的情况: i-q[head]>=k,队头出队,即head++
while(head<=tail && i-q[head]>=k) head++;
//改变队尾的情况: 待入队元素小于队尾a[i]<a[q[tail]] ,则tail--
while(head<=tail && a[i]<a[q[tail]]) tail--;
//入队
q[++tail]=i;
//如果i>=k,输出队头,其下标为q[head]
if(i>=k)
{
printf("%d ",a[q[head]]);
}
}
printf("\n");
//求最大值,用递减序列,输出队头
head=1,tail=0;
for(int i=1;i<=n;i++)
{
//入队前先维护队列,head<=tail则队列非空
//改变队头的情况: i-q[head]>=k,队头出队,即head++
while(head<=tail && i-q[head]>=k) head++;
//改变队尾的情况: 待入队元素大于队尾a[i]>a[q[tail]] ,则tail--
while(head<=tail && a[i]>a[q[tail]]) tail--;
//入队
q[++tail]=i;
//如果i>=k,输出队头,其下标为q[head]
if(i>=k)
{
printf("%d ",a[q[head]]);
}
}
return 0;
}