【模拟试题】滑动窗口(BSOI2604)

【模拟试题】滑动窗口

Description

  给你一个长度为N的数组,一个长为K的滑动的窗体从最左移至最右端,你只能见到窗口的K个数,每次窗体向右移动一位,如下图:
      
  你的任务是找出窗体在各位置时的最大值和最小值。

Input

  第1行:2个整数N,K(K<=N<=1000000) 
  第2行:N个整数,表示数组的N个元素(<=2*10^9) 

Output

  第1行:滑动窗口从左向右移动每个位置的最小值,每个数之间用一个空格分开 
  第2行:滑动窗口从左向右移动每个位置的最大值,每个数之间用一个空格分开

Sample Input

8 3

1 3 -1 -3 5 3 6 7

Sample Output

-1 -3 -3 -3 3 3

3 3 5 5 6 7

Solution

单调队列模板。

维护一个长度为k的单调队列,每次用队首来的出最大和最小值,新加入的数就放在队尾。

如果队首的距离大于k,则head++,即队首出队。若新来的数值比队尾更优,则tail--,即队尾出队。

CODE

#include<iostream>
#include<cstdio>
using namespace std;
int n,k,a[1000005];
struct Queue{int val,pos;}q[1000005];
inline int read(){
	char c;int rec=0,f=1;
	while((c=getchar())<'0'||c>'9')if(c=='-')f=-1;
	while(c>='0'&&c<='9')rec=rec*10+c-'0',c=getchar();
	return rec*f;
}
void work(bool f) {
	int head=1,tail=0,i;
	for(i=1;i<k;i++) {
		if(f)while(a[i]<q[tail].val&&tail>0)tail--;
		else while(a[i]>q[tail].val&&tail>0)tail--;
		q[++tail].val=a[i];q[tail].pos=i;
	}
	for(i=k; i<=n; i++) {
		if(f)while(a[i]<q[tail].val&&tail>=head)tail--;
		else while(a[i]>q[tail].val&&head<=tail)tail--;
		q[++tail].val=a[i];q[tail].pos=i;
		while(q[head].pos+k<=i&&head<=tail)head++;
	    cout<<q[head].val<<" ";
	}cout<<'\n';
	return ;
}
int main() {
	n=read();k=read();
	for(int i=1;i<=n;i++)a[i]=read();
	work(1);work(0);
	return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值