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;

}

你可能感兴趣的:(window)