洛谷 P1886 滑动窗口 /【模板】单调队列
用数组que模拟双端队列(前后都可踢出元素)
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define INF 0x3f3f3f3f
#define lowbit(x) x & (-x)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxN = 1e6 + 5;
int n, k;
int a[maxN];
int que[maxN], id[maxN];
int head, rear;
void init()
{
head = 1;
rear = 0;
}
int main()
{
while(~scanf("%d%d", &n, &k))
{
for(int i = 1; i <= n; i ++ )
scanf("%d", &a[i]);
//找区间最小值
init();
for(int i = 1; i <= n; i ++ )
{
while(head <= rear && que[rear] > a[i])//找到第一个小于a[i]的值的下标,如果没有就是head
-- rear ;
que[ ++ rear] = a[i];
id[rear] = i;
if(id[head] <= i - k)//保证最小元素是在长度范围内的也就是[i - len + 1, i]中的元素
head ++;
if(i >= k)//区间长度足够时就可以输出了。
printf("%d ", que[head]);
}
putchar('\n');
//找区间最大值
init();
for(int i = 1; i <= n; i ++ )
{
while(head <= rear && que[rear] < a[i])//找到第一个大于a[i]的值的下标,如果没有就是head
-- rear ;
que[ ++ rear] = a[i];
id[rear] = i;
if(id[head] <= i - k)
head ++;
if(i >= k)
printf("%d ", que[head]);
}
putchar('\n');
}
return 0;
}
/*
7 3
7 8 -1 12 6 7 11
*/