P1886 滑动窗口&&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

说明

【数据规模】

m≤n≤2000000

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define N 5000050
using namespace std;

void in(int &x){
    register char c=getchar();x=0;int f=1;
    while(!isdigit(c)){if(c==‘-‘) f=-1;c=getchar();}
    while(isdigit(c)){x=x*10+c-‘0‘;c=getchar();}
    x*=f;
}

struct node{
    int x,id;
}mx[N],mi[N];
int hx,tx,hi,ti,n,m,anx[N],ani[N];
int main()
{
    in(n);in(m);
    hx=hi=1;tx=ti=0;
    for(int i=1,x;i<=n;i++){
        in(x);
        while(hx<=tx&&x>=mx[tx].x) --tx;
        mx[++tx].x=x;mx[tx].id=i;
        while(mx[hx].id<=i-m) ++hx;

        while(hi<=ti&&x<=mi[ti].x) --ti;
        mi[++ti].x=x;mi[ti].id=i;
        while(mi[hi].id<=i-m) ++hi;

        if(i>=m) anx[i]=mx[hx].x,ani[i]=mi[hi].x;
    }for(int i=m;i<=n;i++) printf("%d ",ani[i]);
    puts("");
    for(int i=m;i<=n;i++) printf("%d ",anx[i]);
    return 0;
}

P1886 滑动窗口

题目描述

现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口。现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值。

例如:

The array is [1 3 -1 -3 5 3 6 7], and k = 3.

输入输出格式

输入格式:

输入一共有两行,第一行为n,k。

第二行为n个数(<INT_MAX).

输出格式:

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

第二行为每次窗口滑动的最大值

输入输出样例

输入样例#1: 复制

8 3
1 3 -1 -3 5 3 6 7

输出样例#1: 复制

-1 -3 -3 -3 3 3
3 3 5 5 6 7

说明

50%的数据,n<=10^5

100%的数据,n<=10^6

#include<bits/stdc++.h>

#define N 2000005
using namespace std;

void in(int &x){
    register char c=getchar();x=0;int f=1;
    while(!isdigit(c)){if(c==‘-‘) f=-1;c=getchar();}
    while(isdigit(c)){x=x*10+c-‘0‘;c=getchar();}
    x*=f;
}

int n,m,q[N],a[N],ans[N];
int main()
{
    in(n);in(m);
    int head=1,tail=0;
    for(int i=1;i<=n;i++){
        in(a[i]);
        while(head<=tail&&a[q[tail]]>=a[i]) --tail;
        q[++tail]=i;
        while(q[head]<=i-m) ++head;
        ans[i]=a[q[head]];
    }for(int i=1;i<=n;i++) printf("%d\n",ans[i-1]);
    return 0;
}

原文地址:https://www.cnblogs.com/song-/p/9457378.html

时间: 2024-07-29 16:15:01

P1886 滑动窗口&&P1440 求m区间内的最小值的相关文章

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区间内的最小值

第二道单调队列. 这道题就是经典的滑动窗口问题了.要求你求某一个数的前\(m\)位中的最小元素. 先说一句话:单调队列中,队首保存的是最优解,其实是次解,以此类推. 所以我们可以构造一个上升的单调队列,队首弄出来的就是答案. 元素的加入不用说,就是那样子. 重点是这里多了元素的删除.因为窗口的长度有限,你需要把当前窗口没有覆盖住的那些点给pop掉. 可以发现,你要删除的点一定是在队首!并且每一个时刻的最优解也还是队首. 我们只需要加入一个点的同时记录它的加入时间,然后判断是否合法即可. 不知道是

[洛谷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(

洛谷P1886 滑动窗口

P1886 滑动窗口 454通过 1.4K提交 题目提供者darkfire 标签云端↑ 难度普及+/提高 时空限制1s / 128MB 提交  讨论  题解 最新讨论更多讨论 滑动窗口 求标明空间限制 一个奇怪的问题 水印233 为什么会wa一个点,求dalao- 求大神指点 题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. 例如: The array is [1 3 -1 -3 5

洛谷P1886 滑动窗口 单调队列

洛谷P1886 滑动窗口 单调队列 求一个固定长度的区间 最小值和最大值 单调队列求最小值时 1.刚要插入一个数 判断 其是否 小于等于 队尾的数 如果是 则将队尾的数出队 因为求的是队尾到之前的 最小值 ,所以其已经不可能成为 最小值了2.然后数字进队 3.如果队头 已经不再这个区间中,那就队头出队 最大值也是同理 1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cs