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;

}

 

你可能感兴趣的:(window)