NOIP模拟赛 滑动的窗户 单调队列

滑动的窗户

时间限制: 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值