思路:
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;
}