luogu P1886滑动窗口

\(luogu\ P1886\)滑动窗口

题目链接

这道题目比较简单,但是因为经常忘记单调队列做滑动窗口所以写博客来加深一下印象。

如果求区间最小值,我们用发现右端点从前往后扫的方法一个数如果有贡献,当且仅当当前扫描的右端点的前面到这个数中间没有比这个数更小的数,因为如果有比这个数更小的数的话,这个更小的数肯定就会成为区间的最小值。如果一个数没有贡献的时候就是区间的左端点比这个数的下标要大的时候。

所以我们用一个双端队列来维护,每次进入队列的时候检查队尾的数如果比要加入得数大的话,就不断弹出队尾,之后我们将这个数压入队尾,然后我们在检查一下队列头的数的下标是否比枚举到的区间左端点大,如果小的话就弹出队头。这样之后答案就是队头的数。

重点是标程。

#include<bits/stdc++.h>
#include<vector>
using std::vector;
const int N=1e6+100;
vector<int>v;
int n,k;
int a[N];
inline int read()
{
    int ans=0,p=1;
    char ch=getchar();
    while (ch<'0'||ch>'9') {if (ch=='-') p=-1;ch=getchar();}
    while (ch>='0'&&ch<='9') {ans=ans*10-'0'+ch;ch=getchar();}
    return ans*p;
}
int main()
{
    n=read();k=read();
    for (int i=1;i<=n;i++)
    a[i]=read();
    for (int i=1;i<=n;i++)
    {
        while (!v.empty()&&a[v.back()]>a[i]) v.pop_back();
        v.push_back(i);
        if (!v.empty()&&v.front()<i-k+1) v.erase(v.begin(),v.begin()+1);
        if (i>=k) printf("%d ",a[v.front()]);
    }
    printf("\n");
    v.clear();
    for (int i=1;i<=n;i++)
    {
        while (!v.empty()&&a[v.back()]<a[i]) v.pop_back();
        v.push_back(i);
        if (!v.empty()&&v.front()<i-k+1) v.erase(v.begin(),v.begin()+1);
        if (i>=k) printf("%d ",a[v.front()]);
    }
    return 0;
}

如果要开多个队列,推荐使用 \(vector\) ,不信可以开 \(10^5\) 个 \(deque\) 和 \(vector\) 试一下。

原文地址:https://www.cnblogs.com/last-diary/p/11562080.html

时间: 2024-11-07 17:57:16

luogu P1886滑动窗口的相关文章

luogu 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 -

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

P1886 滑动窗口(单调队列)

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

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 说明 [数据规模

洛谷P1886 滑动窗口(POJ.2823 Sliding Window)(区间最值)

To 洛谷.1886 滑动窗口 To POJ.2823 Sliding Window 题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. 例如: The array is [1 3 -1 -3 5 3 6 7], and k = 3. 输入输出格式 输入格式: 输入一共有两行,第一行为n,k. 第二行为n个数(<INT_MAX). 输出格式: 输出共两行,第一行为每次窗口滑动的最小值

洛谷P1886滑动窗口

题目传送门 理解题意:给定一个数列和窗口范围k,求依次向右移动窗口时每次窗口内的最大和最小值. 没什么思维难度,普及+/提高的标签纯粹是吓唬人的,一边扫过去,用两个数组maxx和minn记录每个窗口内的最大最小值,移动过程中用两个变量L和R记录窗口的左右端点,然后判断滑动窗口时最大最小值是否被移出窗口,进入窗口的值是否大于当前最大值或小于当前最小值,做完后L++,R++,用while循环控制轻松水过这题.当然,如果数据比较极端故意卡时就可能没这么轻松了.(不过我估计也不太可能会有什么题目出这么可

luogu 1886 滑动窗口

题目描述 现在有一堆数字共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

落谷P1886 滑动窗口~

很好用的线性求变换区间最值的方法,比线段树快 用到了优先队列的算法 据说能用STL双向队列解但我不会QAQ #include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> using namespace std; int n,k; int ans,l,r,a,b; int num[1000007]; int q[1000007],q