Sliding Window(POJ-2823)


1 题意

  给定一个整数序列和一个滑动窗口大小,让滑动窗口在整数序列上滑动,求出滑动窗口内的最小值和最大值。
  链接:link

2 思路

  用单调队列维护窗口最大最小值。
  单调队列分为最大队列和最小队列,其内部元素分别是单调递减和单调递增的,并用来维护窗口最大值和最小值。
  下面说明一下如何用最大队列维护窗口最大值,最小队列则相反,这里不再介绍。

  1. 先判断队列首元素的位置与当前元素的位置之差是否大于窗口大小,如果大于则要将队首元素出队列
  2. 判断队尾元素是否小于或等于当前元素,如果是的话就将队尾元素出队列(这样可以保证队头永远是当前窗口最大的元素)
  3. 将当前元素入队列,并记录下该元素的位置,最后将队头元素记录下来即可(即为当前窗口的最大值)

2.1 时间复杂度分析

  每个元素压入和弹出单调队列一次,所以时间复杂度为 O ( n ) \mathcal{O}(n) O(n)

2.2 实现

#include<iostream>
#include<cstdio>
using namespace std;
const int MAXN=1e6+10;
int n,k,id[MAXN];
int val[MAXN],Fmax[MAXN],Fmin[MAXN];
int q[MAXN],head,tail;
void col_max(){
    head=1;tail=0;
    for(int i=1;i<=n;++i){
        while(id[head]<i-k+1&&head<=tail) head++;
        while(val[i]>=q[tail]&&head<=tail) tail--;
        id[++tail]=i;q[tail]=val[i];
        Fmax[i]=q[head];
    }
}
void col_min(){
    head=1;tail=0;
    for(int i=1;i<=n;++i){
        while(id[head]<i-k+1&&head<=tail) head++;
        while(val[i]<=q[tail]&&head<=tail) tail--;
        id[++tail]=i;q[tail]=val[i];
        Fmin[i]=q[head];
    }
}
int main(){
    scanf("%d %d",&n,&k);
    for(int i=1;i<=n;++i) scanf("%d",&val[i]);
    col_max();col_min();
    for(int i=k;i<=n;++i) printf("%d ",Fmin[i]);
    printf("\n");
    for(int i=k;i<=n;++i) printf("%d ",Fmax[i]);
    printf("\n");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值