POJ 2823 Sliding Window(单调队列)

思路:

1. deq 里面存放的是窗口里面的最小/大值(存在重复元素),是一个单调队列

2. 当窗口滑动时,比较出窗口的元素与队列首元素比较,如果相等,deq 首元素出队列。比较入窗口的元素在队列里面找到不小于/不大于自身元素值的位置。

3. 对于单调队列查找,相当于有序队列查找,即可以采取二分搜索优化。但是本题似乎优化后的效果还不如枚举的效果。

 

#include <iostream>
#include <algorithm>
using namespace std;

const int MAXN = 1000010;
int arr[MAXN], deq[MAXN];

int main()
{
    int N, K;
    while (scanf("%d %d", &N, &K) != EOF)
    {
        for (int i = 1; i <= N; ++i)
            scanf("%d", &arr[i]);

        int s = 0, e = -1;

        for (int i = 1; i <= N; ++i)
        {
            if (i > K && arr[i-K] == deq[s])
                ++s;

            int l = s, r = e;
            while (l <= r)
            {
                int m = (l + r) >> 1;
                if (deq[m] <= arr[i])
                    l = m + 1;
                else
                    r = m - 1;
            }
            e = l - 1;

            deq[++e] = arr[i];

            if (i == K)
                printf("%d", deq[s]);
            else if (i > K)
                printf(" %d", deq[s]);
        }
        printf("\n");

        s = 0, e = -1;

        for (int i = 1; i <= N; ++i)
        {
            if (i > K && arr[i-K] == deq[s])
                ++s;

            int l = s, r = e;
            while (l <= r)
            {
                int m = (l + r) >> 1;
                if (deq[m] >= arr[i])
                    l = m + 1;
                else
                    r = m - 1;
            }
            e = l - 1;

            deq[++e] = arr[i];

            if (i == K)
                printf("%d", deq[s]);
            else if (i > K)
                printf(" %d", deq[s]);
        }
        printf("\n");
    }
    return 0;
}
posted @ 2013-02-26 22:47  kedebug  阅读(245)  评论(0)    收藏  举报