P1440 求m区间内的最小值

第二道单调队列。



这道题就是经典的滑动窗口问题了。要求你求某一个数的前\(m\)位中的最小元素。

先说一句话:单调队列中,队首保存的是最优解,其实是次解,以此类推

所以我们可以构造一个上升的单调队列,队首弄出来的就是答案。

元素的加入不用说,就是那样子。

重点是这里多了元素的删除。因为窗口的长度有限,你需要把当前窗口没有覆盖住的那些点给pop掉。

可以发现,你要删除的点一定是在队首!并且每一个时刻的最优解也还是队首。

我们只需要加入一个点的同时记录它的加入时间,然后判断是否合法即可。

不知道是先删除后加入还是怎么的,我并没有什么深刻理解。

luogu日报的单调队列真的写得特别好!飞机票

代码:

#include<cstdio>
#include<queue>

const int maxn = 2000005;
int a[maxn], n, m;
struct Nodes
{
    int tim, val;
};
std::deque<Nodes> q;
int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
    q.push_back((Nodes){1, a[1]});
    printf("0\n");
    for(int i = 2; i <= n; i++)
    {
        // delete
        if(q.front().tim + m < i) q.pop_front();
        printf("%d\n", q.front().val);
        // insert
        while(!q.empty() && a[i] < q.back().val)
        {
            q.pop_back();
        }
        q.push_back((Nodes){i, a[i]});
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Garen-Wang/p/9525357.html

时间: 2024-07-29 16:16:03

P1440 求m区间内的最小值的相关文章

P1886 滑动窗口&amp;&amp;P1440 求m区间内的最小值

单调队列入门题 P1440 求m区间内的最小值 题目描述 一个含有n项的数列(n<=2000000),求出每一项前的m个数到它这个区间内的最小值.若前面的数不足m项则从第1个数开始,若前面没有数则输出0. 输入输出格式 输入格式: 第一行两个数n,m. 第二行,n个正整数,为所给定的数列. 输出格式: n行,第i行的一个数ai,为所求序列中第i个数前m个数的最小值. 输入输出样例 输入样例#1: 复制 6 2 7 8 1 4 3 2 输出样例#1: 复制 0 7 7 1 1 3 说明 [数据规模

luogu P1440 求m区间内的最小值

题目描述 一个含有n项的数列(n<=2000000),求出每一项前的m个数到它这个区间内的最小值.若前面的数不足m项则从第1个数开始,若前面没有数则输出0. 输入输出格式 输入格式: 第一行两个数n,m. 第二行,n个正整数,为所给定的数列. 输出格式: n行,第i行的一个数ai,为所求序列中第i个数前m个数的最小值. 输入输出样例 输入样例#1: 6 2 7 8 1 4 3 2 输出样例#1: 0 7 7 1 1 3 说明 [数据规模] m≤n≤2000000 线段树 维护最小值 #inclu

[洛谷P1440]求m区间内的最小值

题目大意:给你n个数,求出每个数前m位的最小值 题解:单调队列,用一个可以双向弹出的队列来存一串数,满足里面的数具有单调性,我们可以假设它是单调递增的,即求最小的数.那么可以把要插入的这个数与队尾元素比较,如果队尾的数大,那么插入它就不满足单调性了,那么我们就从队尾删除元素,直到比队尾元素大.这样就可以满足要求.如果队首元素已经超出了m的范围,就从队首删除元素,队首的元素就一直是答案. #include<cstdio> using namespace std; int n,m; int q[2

单调队列——求m区间内的最小值

单调队列,顾名思义是指队列内的元素是有序的,队头为当前的最大值(单调递减队列)或最小值(单调递增序列),以单调递减队列为例来看队列的入队和出队操作: 1.入队: 如果当前元素要进队,把当前元素和队尾元素比较,如果当前元素小于队尾元素,那么当前元素直接进队,如果当前元素大于队尾元素,那么队尾出队,将当前元素和新的队尾再做比较,直到当前元素大于队尾元素或者队列为空.单调队列只能在队尾插入元素,队尾和队头都可以删除元素. 2.出队: 出队直接取队头即可,因为用单调队列就是为了取最值,而队头就是最值.

洛谷1440 求m区间内的最小值

本题地址:http://www.luogu.org/problem/show?pid=1440 题目描述 一个含有n项的数列(n<=2000000),求出每一项前的m个数到它这个区间内的最小值.若前面的数不足m项则从第1个数开始,若前面没有数则输出0. 输入输出格式 输入格式: 第一行两个数n,m. 第二行,n个正整数,为所给定的数列. 输出格式: n行,第i行的一个数ai,为所求序列中第i个数前m个数的最小值. 输入输出样例 输入样例#1: 6 2 7 8 1 4 3 2 输出样例#1: 0

luoguP1440 求m区间内的最小值

emmmmmm 看到这道题的第一反应嘛 (区间最小,大概是RMQ吧 然后,华丽丽的80分 (题解说st表会T两个点,可是我是MLE emmmm... 貌似st表不能做,有一个滚动数组的优化,可以看看题解学一下 这里我改用了单调队列的做法 (本来用的STL的队列,但是学长说不方便,开一个数组即可 [而且我STL队列还没写出来23333 emmmm(不知道怎么讲 看代码吧 #include<cstdio> using namespace std; const int maxn = 2000010;

求m区间内的最小值(洛谷_1440)

这题用队列随便搞一下就好了. 就是可能有些细节 #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; inline int read(){ int t=1,num=0;char c=getchar(); while(c>'9'||c<'0'){if(c=='-')t=-1;c=getchar();} while(

2017乌鲁木齐区域赛K(容斥原理【求指定区间内与n互素的数的个数】)

#include<bits/stdc++.h>using namespace std;const long long mod = 998244353;typedef const long long ll;vector<long long>p;long long inv(long long x,long long y)//快速幂求逆元模板(以乘代除){    long long r=1;    while(y>0)    {        if(y&1)        

hdu 1806 Frequent values(给定一个非降序数组,求任意区间内出现次数最多的数的次数)

1.题目解析可见<训练指南>P198 2代码: #include<cstdio> #include<cstring> #include<cmath> #define Min(a,b) ((a)<(b)?(a):(b)) #define Max(a,b) ((a)>(b)?(a):(b)) #define N 100005 #define INF 1<<30 using namespace std; int a[N]; int valu