单调队列 - 滑动窗口 - 典

滑动窗口,答案一般在队首,队尾用于插入新的点。

1:窗口大小不变,依次滑动窗口,求窗口内最大值和最小值

P1886 滑动窗口 /【模板】单调队列

有一个长为 n 的序列 a,以及一个大小为 k 的窗口。现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值。

输出共两行,第一行为每次窗口滑动的最小值
第二行为每次窗口滑动的最大值

int a[N],q[N],p[N];
int n,m;
//1 3 -1 -3 5 3 6 7
void mi(){
    int h = 1,t = 0;//head -> tail 清空队列
    for(int i=1;i<=n;i++){//枚举
        while(h <= t && a[q[t]] >= a[i])//队列不空且新元素更优
            t--;//队尾出队
        q[++t] = i;//队尾入队
        if(q[h] + m <= i)//队头出队
            h++;
        if(i >= m)
        cout<<a[q[h]]<<" ";
    }
}

void ma(){
    int h = 1, t = 0;//head -> tail
    for(int i=1;i<=n;i++){
        while(h <= t && a[i] >= a[q[t]]) 
            t--;
        q[++t] = i;
        if(q[h] + m <= i)
            h++;
        if(i >= m)
        cout<<a[q[h]]<<" ";
    }
}

2:连续子序列的最大和

int a[N],q[N],p[N],s[N];
int n,m,ans;

void mi(){
    int h = 0 , t = 0;
    q[0] = 0 , ans = s[1];
    for(int i=1;i<=n;i++){
        //判断队头元素是否要出队
        if(h <= t && q[h] + m < i) h++;
        //使用队头元素
        ans = max(ans,s[i]-s[q[h]]);
        //判断队尾元素是否需要出队(看是不是最优)
        //找最小值时 队尾比该值大就出队 
        while(h <= t && s[q[t]] >= s[i])
            t--;
        //队尾插入新元素
        q[++t] = i;
    }
    cout<<ans;
}
/*
    s[i]-min(s[j],i-m <=j<= i-1)
    即用单调队列找出窗口中的最小值
*/
int main(){
	IOS;
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        s[i] = s[i-1] + a[i];
    }
   ans = 0;
   mi();
}

3:求每一个数左边第一个比他小的数

int a[N],q[N],n,m;
void mi(){//没有用到h 
    int h = 1 , t = 0;
    for(int i=1;i<=n;i++){
        //出队 直到找到比a[i]小的
        while(t && a[i]<=a[q[t]]) t--;
        if(t==0) cout<<"-1"<<" ";//没找到
        else cout<<a[q[t]]<<" ";
        q[++t] = i;//继续入队
    }
}
/*
一个数如果被出队 他就不可能再是某个数的答案
10
4 7 6 8
8的答案是6 不会是已经出队的7
*/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值