滑动的窗户
【题目描述】 在一个包含 n 个元素的数组上,有一个长度为 k 的窗户在从左
向右滑动。窗户每滑动到一个位置,我们都可以看到 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
对于窗户滑动过的每个位置,请给出窗户内 k 个元素的最小值和最大值。
【输入】
输入文件:window.in
输入的第一行包括两个整数 n,k,n 表示数组的长度,k 表示窗户的长度。
接下来一行包括 n 个整数,表示这个 n 个元素的数组。
【输出】
输出文件:window.out
输出包含两行,每行包括 n-k+1 个整数,第一行表示窗户从左到右滑动过程
中的最小值,第二行表示窗户从左到右滑动过程中的最大值。
【输入样例】
8 3
1 3 -1 -3 5 3 6 7
【输出样例】
-1 -3 -3 -3 3 3
3 3 5 5 6 7
【数据范围】
对于 100%的数据,3<=n<=1000000,1<=k<=n,数组中的每个元素均在 int 范
围内
单调队列板子
#include<cstdio>
#include<queue>
#include<cstdlib>
#include<algorithm>
#include<stack>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 2000000;
int A[maxn];
int head1,tail1;
int head2,tail2;
int fmax[maxn],fmin[maxn];
int cnt;
int Qx[maxn],Qd[maxn];
int numx[maxn],numd[maxn];
int main()
{
freopen("window.in","r",stdin);
freopen("window.out","w",stdout);
int n,m;
scanf("%d%d",&n,&m);
for(int i = 1;i <= n;i++) scanf("%d",&A[i]);
head1 = 1;tail1 = 0;head2 = 1;tail2 = 0;
for(int i = 1;i < m;i++){
while(Qx[tail1] >= A[i]&&tail1 >= head1) --tail1;
Qx[++tail1] = A[i];numx[tail1] = i;
while(Qd[tail2] <= A[i]&&tail2 >= head2) --tail2;
Qd[++tail2] = A[i];numd[tail2] = i;
}
for(int i = m;i <= n;i++){
while(Qx[tail1] >= A[i]&&tail1 >= head1) --tail1;
Qx[++tail1] = A[i];numx[tail1] = i;
while(Qd[tail2] <= A[i]&&tail2 >= head2) --tail2;
Qd[++tail2] = A[i];numd[tail2] = i;
while(i-m+1 > numx[head1]) head1++;
while(i-m+1 > numd[head2]) head2++;
fmax[i-m+1] = Qd[head2];
fmin[i-m+1] = Qx[head1];
}
for(int i = 1;i <= n-m+1;i++)
printf("%d ",fmin[i]);
printf("\n");
for(int i = 1;i <= n-m+1;i++)
printf("%d ",fmax[i]);
return 0;
}

浙公网安备 33010602011771号