poj 2823 Sliding Window 单调队列

poj 2823 Sliding Window
//poj 2823  Sliding Window

//单调队列

//以下是复制别人的思路的,自己写的代码过不了,这代码也是模仿别人的

//这题还可以用单调队列进行求解。开两个队列,一个维护最大值,
//一个维护最小值。下面叙述最大队列,最小队列的方法类似。 

//最大队列保证队列中各个元素大小单调递减(注意,不是单调不上升),
//同时每个元素的下标单调递增。这样便保证队首元素最大,而且更新的
//时候队首永远是当前最大。因此,这个队列需要在两头都可以进行删除,
//在队尾插入。

//维护方法:在每次插入的时候,先判断队尾元素,如果不比待插入元素
//大就删除,不断删除队尾直到队尾元素大于待插入元素或者队空。删除
//的时候,判断队首,如果队首元素下标小于当前段左边界就删除,不断
//删除队首直到队首元素下标大于等于当前段左边界(注意:这时队列肯
//定不为空),队首元素就是当前段的最优解。



#include <stdio.h>
#include <string.h>

#define N 1000005

int input()
{
    char ch;
    int sign = 1, num = 0;
    while(ch = getchar(), ch == '\n' || ch == ' ');

    if(ch == EOF)
        return EOF;

    if(ch == '-')
    {
        sign = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        num = num * 10 + ch - '0';
        ch = getchar();
    }
    return sign * num;
}

int arr[N], mn[N], mx[N], time[N], ans[N];
int len, k;

void getMin()
{
    int head = 1, tail = 0;
    for(int i = 1; i <= len; ++i)
    {       //删除队尾比要插入的数大的数
        while(head <= tail && mn[tail] >= arr[i])
            tail--;
        mn[++tail] = arr[i];    //把要插入的数插入到队尾,因此
        time[tail] = i;         //队列后面的数肯定比前面的数晚过期
        if(i >= k)
        {
            while(time[head] <= i - k)//注意:这里要等,eg:当i=k+1时
                head++;               //第一个就过期了
            ans[i-k] = mn[head];
        }
    }
}

void getMax()
{
    int head = 1, tail = 0;
    for(int i = 1; i <= len; ++i)
    {
        while(head <= tail && mx[tail] <= arr[i])
            tail--;
        mx[++tail] = arr[i];
        time[tail] = i;
        if(i >= k)
        {
            while(time[head] <= i - k)
                head++;
            ans[i-k] = mx[head];
        }
    }
}

void print()
{
    int end = len-k;    //总的有 1+end 组 宽度为 k 的数
    for(int i = 0; i <= end; ++i)
    {
        printf("%d", ans[i]);
        if(i != end)
            putchar(' ');
    }
    puts("");
}

int main()
{
    while(scanf("%d%d", &len, &k) != EOF)
    {
        for(int i = 1; i <= len; ++i)
            arr[i] = input();
        getMin();
        print();
        getMax();
        print();
    }
    return 0;
}
原文地址:https://www.cnblogs.com/gabo/p/2512158.html