有一个长为 n 的序列 a,以及一个大小为 k 的窗口。现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值。
例如,对于序列 [1,3,−1,−3,5,3,6,7] 以及 k=3,有如下过程:
窗口位置 最小值 最大值
1 3 -1] -3 5 3 6 7 −1 3
1 [3 -1 -3] 5 3 6 7 −3 3
1 3 [-1 -3 5] 3 6 7 −3 5
1 3 -1 [-3 5 3] 6 7 −3 5
1 3 -1 -3 [5 3 6] 7 3 6
1 3 -1 -3 5 [3 6 7] 3 7
输入格式
输入一共有两行,第一行有两个正整数 n,k。 第二行 n 个整数,表示序列 a
输出格式
输出共两行,第一行为每次窗口滑动的最小值
第二行为每次窗口滑动的最大值
输入输出样例
输入
8 3 1 3 -1 -3 5 3 6 7
输出
-1 -3 -3 -3 3 3 3 3 5 5 6 7
初始时,左右变量l(l1),r(r1)分别初始化为1和0,表示左窗口和右窗口,注意这里是左开右闭,因此初始窗口[0,0)区间没有元素,符合我们的初始定义开始循环遍历整个数组元素,判断当前r是否超过l,且判断更新值是否大于或小于记录的最值,是退出循环,否则执行第3步然后r指针开始向右移动一个长度,l左移一个长度,并更新窗口内的区间数据
#include <bits/stdc++.h>
using namespace std;
long long a[10000000];
long long b[10000000];
long long c[10000000];
long long l=1,r=0,l1=1,r1=0;
long long n,m,q=0,e=0;
long long b1[10000000];
long long c1[10000000];
int main()
{
long long x,y,z;
scanf("%lld%lld",&n,&m);
for(x=1;x<=n;x++)
{
scanf("%lld",&a[x]);
}
for(x=1;x<=n;x++)
{
while(l<=r&&a[b[r]]>=a[x])
r--; //判断入列的位置
b[++r]=x; //入列
if(b[l]<x-m+1)//窗口长度
l++; //出列
while(l1<=r1&&a[c[r1]]<=a[x])
r1--;
c[++r1]=x;
if(c[l1]<x-m+1)l1++;
if(x>=m)
{
b1[q++]=b[l];
c1[e++]=c[l1];
}
}
for(x=0;x<q;x++)
printf("%lld ",a[b1[x]]);
printf("\n");
for(x=0;x<e;x++)
printf("%lld ",a[c1[x]]);
return 0;
}