POJ 2823 Sliding Window滑窗

金典的单调队列的题目。

题目大意给你n个数和一个k(0  < k ,n < 10^6),一个长度为k的窗口在长度为为n的序列滑动,没滑动一个位置,求出这个窗口里的最小值和最大值,先输出最小值得序列,再输出最大值的序列。

n很大不能在每一个窗口中去遍历出最小值跟最大值,这里用到一个单调队列。此处只做出最小值得序列求解,最大值序列同理。

用一个单调非严格递增的队列去维护此时最小值。

<pre name="code" class="cpp">
#include <cstdio>
#define MAXN 1000007
int arr[MAXN];
int que[MAXN * 10];
int read()//快速读入
{
    char ch;
    int v = 0, s = 1;
    while(ch = getchar(), ch == ' ' || ch == '\n' || ch == '\t');
    if(ch == '-') s = -1;
    else v = ch - '0';
    while(ch = getchar(), ch != ' ' && ch != '\n' && ch != '\t') v = v * 10 + ch - '0';
    return v * s;
}
void write(int x, char c) //快速输出
{
    char ch[10], pos = 0;
    if(x < 0) putchar('-');
    x = x > 0? x: -x;
    if(!x) putchar('0');
    while(x)
    {
        ch[pos++] = x % 10;x /= 10;
    }
    while(pos)
        putchar(ch[--pos] + '0');
    putchar(c);
}
int main()
{
    int n, k;
    while(~scanf("%d%d", &n, &k))
    {
        if(n < k) k = n;
        for(int i = 0; i < n; ++i)
            arr[i] = read();
        int front = 0, rear = -1;
        que[++rear] = 0;
        for(int i = 1; i <= n; ++i)
        {
            if(i >= k )
            {
                write(arr[que[front]], i < n? ' ': '\n');
                if(i - que[front] >= k) front++;
            }
            while(rear >= front && arr[que[rear]] > arr[i])
                rear--;
            que[++rear] = i;
        }
        front = 0, rear = -1;
        que[++rear] = 0;
        for(int i = 1; i <= n; ++i)
        {
            if(i >= k)
            {
                write(arr[que[front]], i < n? ' ': '\n');
                if(i - que[front] >= k) front++;
            }
            while(rear >= front && arr[que[rear]] < arr[i])
                rear--;
            que[++rear] = i;
        }
    }
    return 0;
}


 
 

你可能感兴趣的:(window,Sliding,POJ2823,POJ解题报告,滑窗)