滑动窗口

【题目描述】

给定一个长度为N的数组,一个长为K的滑动窗体从最左端移至最右端,移动时只能看到窗体内的K个数,每次窗体向右移动一位,如下表:

Window position Min value Max value
[ 1 3 -1 ] -3 5 3 6 7 -1 3
1 [ 3 -1 -3 ] 5 3 6 7 -3 3
1 3 [ -1 -3 5 ] 3 6 7 -3 5
1 3 -1 [ -3 5 3 ] 6 7 -3 5
1 3 -1 -3 [ 5 3 6 ] 7 3 6
1 3 -1 -3 5 [ 3 6 7 ] 3 7

现要求找出窗体在各位置时的Max value与Min value。

【输入描述】

第一行输入两个整数N、K;

第二行输入长度为N的数组。

【输出描述】

第一行输出每个位置的Min value;

第二行输出每个位置的Max value。

【样例输入】

8 3

1 3 -1 -3 5 3 6 7

【样例输出】

-1 -3 -3 -3 3 3

3  3  5  5  6 7

【数据范围及提示】

对于20%的数据,n <= 500;

对于50%的数据,n <= 100000;

对于100%的数据,n <= 1000000。

源代码:

#include<cstdio>
int n,k,i[1000001],Q[1000001],P[1000001];
void Min()
{
    int Head=1,Tail=0;
    for (int a=0;a<k-1;a++) //初始化。
    {
        while (Head<=Tail&&Q[Tail]>=i[a])
          Tail--;
        Q[++Tail]=i[a];
        P[Tail]=a;
    }
    for (int a=k-1;a<n;a++) //移动状态。
    {
        while (Head<=Tail&&Q[Tail]>=i[a]) //增尾。
          Tail--;
        Q[++Tail]=i[a];
        P[Tail]=a;
        while (P[Head]<a-k+1) //去头。
          Head++;
        printf(a==n-1?"%d
":"%d ",Q[Head]); //注意换行。
    }
}
void Max() //同理于上。
{
    int Head=1,Tail=0;
    for (int a=0;a<k-1;a++)
    {
        while (Head<=Tail&&Q[Tail]<=i[a])
          Tail--;
        Q[++Tail]=i[a];
        P[Tail]=a;
    }
    for (int a=k-1;a<n;a++)
    {
        while (Head<=Tail&&Q[Tail]<=i[a])
          Tail--;
        Q[++Tail]=i[a];
        P[Tail]=a;
        while (P[Head]<a-k+1)
          Head++;
        printf(a==n-1?"%d
":"%d ",Q[Head]);
    }
}
int main() //裸单调队列。
{
    scanf("%d%d",&n,&k);
    for (int a=0;a<n;a++)
      scanf("%d",&i[a]);
    Min();
    Max();
    return 0;
}
原文地址:https://www.cnblogs.com/Ackermann/p/5861161.html