滑动的窗户
时间限制: 3 Sec 内存限制: 256 MB
题目描述
在一个包含n个元素的数组上,有一个长度为k的窗户在从左向右滑动。窗户每滑动到一个位置,我们都可以看到k个元素在窗户中。
对于窗户滑动过的每个位置,请给出窗户内k个元素的最小值和最大值。
输入
输入的第一行包括两个整数n,k,n表示数组的长度,k表示窗户的长度。
接下来一行包括n个整数,表示这个n个元素的数组。
输出
输出包含两行,每行包括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>
#define re register int
#define si 1000010
using namespace std;
int n,k,a[si],num[si],q[si];
int tail,head,mi[si],ma[si];
inline int read() {
int x=0,cf=1;
char ch=getchar();
while(ch<'0'||ch>'9') {
if(ch=='-') cf=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') {
x=(x<<3)+(x<<1)+(ch^48);
ch=getchar();
}
return x*cf;
}
int main() {
n=read(),k=read();
for(re i=1;i<=n;i++) a[i]=read();
head=1,tail=0;
for(re i=1;i<=n;i++) {
while(num[head]<i-k+1&&head<=tail) head++;
while(a[i]<=q[tail]&&head<=tail) tail--;
num[++tail]=i,q[tail]=a[i],mi[i]=q[head];
}
head=1,tail=0;
for(re i=1;i<=n;i++) {
while(num[head]<i-k+1&&head<=tail) head++;
while(a[i]>=q[tail]&&head<=tail) tail--;
num[++tail]=i,q[tail]=a[i],ma[i]=q[head];
}
for(re i=k;i<=n;i++) printf("%d ",mi[i]);
printf("\n");
for(re i=k;i<=n;i++) printf("%d ",ma[i]);
return 0;
}