P1440 求m区间内的最小值(单调队列)

这篇博客介绍了一种利用单调队列优化的筛数算法,通过在O(n)的时间复杂度内筛选出给定长度m内的最小整数,并在过程中实时输出。代码示例展示了如何维护队列的单调性并确保筛选出的数满足条件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:
在这里插入图片描述
思路:用单调队列去不断进行筛数操作,O(n)扫一遍,两个while第一个while是使队列是单调的,如果不符合就弹数,第二个while是使队列里的元素要满足前m个。

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e6+100;
int a[maxn];
deque<int >m1;
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    printf("%d\n",0);
    for(int i=1;i<n;i++){
        scanf("%d",&a[i]);
        while(m1.size()&&a[m1.back()]>a[i]){
            m1.pop_back();
        }
        m1.push_back(i);
        while(i-m>=m1.front()){
            m1.pop_front();
        }
        printf("%d\n",a[m1.front()]);
    }
    return 0;
}

### 使用单调栈计算区间最大值与区间最小值 #### 计算区间最大值 对于解滑动窗口中的最大值问题,可以利用单调递减栈来高效完成。每当遇到一个新的元素时,如果该元素大于等于栈顶元素,则持续弹出栈顶直到找到一个更大的元素或将栈清空;之后将当前元素及其索引压入栈中。此时栈底到栈顶保存着从大到小排列的一系列候选者,而最新的那个就是当前窗口内的最大值。 ```python def maxSlidingWindow(nums, k): from collections import deque q = deque() result = [] for i in range(len(nums)): while q and nums[q[-1]] <= nums[i]: q.pop() q.append(i) if q[0] == i - k: q.popleft() if i >= k - 1: result.append(nums[q[0]]) return result ``` 此代码实现了基于单调递减栈的滑动窗口最大值查找算法[^2]。 #### 计算区间最小值 同样地,在寻找滑动窗口内的最小值方面也可以采用类似的策略——构建一个单调递增栈。当新加入的数据小于等于栈顶端所指向位置处的数据时,不断移除顶部较小数值直至满足条件为止;随后把新的数据连同其对应的下标记入队列之中。最后位于栈首部的就是当前考察范围里最小的那个数了。 ```python def minSlidingWindow(nums, k): from collections import deque q = deque() result = [] for i in range(len(nums)): while q and nums[q[-1]] >= nums[i]: q.pop() q.append(i) if q[0] == i - k: q.popleft() if i >= k - 1: result.append(nums[q[0]]) return result ``` 上述程序展示了怎样运用单调递增栈来进行滑动窗口最小值查询操作[^3]。 这两种方法均能在O(n)时间复杂度内解决问题,并且只需要线性的额外空间开销。它们广泛应用于各种实际场景当中,比如股票价格波动分析、实时流量监控等场合下的快速响应需
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值