【单调队列】--滑动窗口

题目链接

给定一个大小为n≤106n≤106的数组。

有一个大小为k的滑动窗口,它从数组的最左边移动到最右边。

您只能在窗口中看到k个数字。

每次滑动窗口向右移动一个位置。

以下是一个例子:

该数组为[1 3 -1 -3 5 3 6 7],k为3。

窗口位置 最小值 最大值
[1 3 -1] -3 5 3 6 7 -1 3
1 [3 -1 -3] 5 3 6 7 -3 3
1 3 [-1 -3 5] 3 6 7 -3 5
1 3 -1 [-3 5 3] 6 7 -3 5
1 3 -1 -3 [5 3 6] 7 3 6
1 3 -1 -3 5 [3 6 7] 3 7

您的任务是确定滑动窗口位于每个位置时,窗口中的最大值和最小值。

输入格式

输入包含两行。

第一行包含两个整数n和k,分别代表数组长度和滑动窗口的长度。

第二行有n个整数,代表数组的具体数值。

同行数据之间用空格隔开。

输出格式

输出包含两个。

第一行输出,从左至右,每个位置滑动窗口中的最小值。

第二行输出,从左至右,每个位置滑动窗口中的最大值。

输入样例:

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

输出样例:

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

思路:首先想暴力的做法,时间复杂度是O(n*k),然后再来看是否可以优化的地方。以输窗口最小值为例:可以发现,在一个窗口中,如果来了一个小的数,那么比此数大的数就永远不会成为最小值了,所以我们在入队的时候,需要把此数前面比他大的数全部出队,联想一下,每次入队后,每个元素的左边都会比他小,因为比他大的都出队了。所以可见,这会形成一个单调递增的队列,所以每滑动一次窗口,只需要输出队头就行了,队头就是最小的。还有一点值的说的是,队列里只需要存放一个元素时,只需要存放此元素在原数组中的下标。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6+10;

int n,k;

int a[maxn]; //原数组
int q[maxn]; //保存元素的下标
void up(){
    int hh = 0,tt = -1;
    for(int i = 0;i<n;i++){
        if(hh <=tt && q[hh] < i-k+1) hh++; //出队,hh<=tt表示队列有元素
        while(hh<=tt && a[q[tt]] >= a[i]) tt--;//保持队列递增
        q[++tt] = i;//入队
        if(i>=k-1) printf("%d ",a[q[hh]]);//窗口达到K,才开始输出
    }
    cout<<endl;
}

void down(){ //和上面几乎一样,只是把改了一下大于小于
    int hh = 0,tt = -1;
    for(int i = 0;i<n;i++){
        if(hh<=tt && q[hh] < i-k+1) hh++;
        while(hh<=tt && a[q[tt]] <= a[i]) tt--;
        q[++tt] = i;
        if(i>=k-1) printf("%d ",a[q[hh]]);
    }
    cout<<endl;
} 

int main(){
    cin>>n>>k;
    for(int i = 0;i<n;i++) scanf("%d",&a[i]);
    up();
    down();
    return 0;
}

原文地址:https://www.cnblogs.com/bigbrox/p/11379355.html

时间: 2024-10-17 15:50:16

【单调队列】--滑动窗口的相关文章

详解--单调队列 经典滑动窗口问题

单调队列,即单调的队列.使用频率不高,但在有些程序中会有非同寻常的作用. 动态规划·单调队列的理解 做动态规划时常常会见到形如这样的转移方程: f[x] = max or min{g(k) | b[x] <= k < x} + w[x] (其中b[x]随x单调不降,即b[1]<=b[2]<=b[3]<=...<=b[n]) (g[k]表示一个和k或f[k]有关的函数,w[x]表示一个和x有关的函数) 这个方程怎样求解呢?我们注意到这样一个性质:如果存在两个数j, k,使

滑动窗口的单调队列

今天的训练赛HDU 4122,卡到最后也没出来,结束后和队友冷静分析代码后才发现错在一个简单的错误上,修改后A了 赛后看题解,大家的题解中大都提到了要用单调队列. 去网上搜单调队列..文章无外乎就两种..= =  抄袭好严重呀 1.http://zhonghuan.info/2014/09/16/%E6%B5%85%E6%9E%90%E5%8D%95%E8%B0%83%E9%98%9F%E5%88%97/ 简单的单调队列 2.http://blog.pureisle.net/archives/4

单调队列(滑动窗口问题)

Description An array of size n ≤ 106 is given to you. There is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves rightwards b

luoguP1886 滑动窗口 [单调队列]

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

[BZOJ 1047][HAOI 2007]理想的正方形(二维滑动窗口+单调队列)

题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1047 思路:裸的二维上的滑动窗口问题,可以借鉴一维滑动窗口的思路.首先预处理出每一列j的.以第i行元素为结尾.长度为n的区间的最大值maxv[i][j].最小值minv[i][j],然后再搞每一行,求出以每一行i结尾.行标上长度为n的区间.以第j列结尾.列标上长度为n的区间得到的二维区间最大值与最小值之差,遍历每一行得到这个差的最小值即为答案. #include <iostrea

cogs 495. 滑动窗口 单调队列

495. 滑动窗口 ★★   输入文件:window.in   输出文件:window.out   简单对比时间限制:2 s   内存限制:256 MB [问题描述] 给你一个长度为N的数组,一个长为K的滑动的窗体从最左移至最右端,你只能见到窗口的K个数,每次窗体向右移动一位,如下表: Window position Min value Max value [1 3 -1] -3 5 3 6 7 -1 3 1 [3 -1 -3] 5 3 6 7 -3 3 1 3 [-1 -3 5]3 6 7 -

数据结构——单调栈&amp;单调队列(解决滑动窗口问题)

单调队列解答: /*******************单调队列!=优先队列单调队列是为了保证队列内的元素具有单调性,在保持了元素原本顺序的同时,对元素进行了过滤,舍弃了会影响单调性的元素而优先队列本质上还是个队列不会舍弃任何元素,每个元素都在队列之中,但是在队列中的位置由优先队列定义的优先级来确定,损失了原数组中的数据相对位置关系.所以很显然,单调队列是解决:寻找在某元素左侧区间或者右侧区间的最值问题,而优先队列的应用是寻找整个区间内的最高优先级别的内容./******************

Acwing 154 滑动窗口(单调队列)经典模板

给定一个大小为n≤106n≤106的数组. 有一个大小为k的滑动窗口,它从数组的最左边移动到最右边. 您只能在窗口中看到k个数字. 每次滑动窗口向右移动一个位置. 以下是一个例子: 该数组为[1 3 -1 -3 5 3 6 7],k为3. 窗口位置 最小值 最大值 [1 3 -1] -3 5 3 6 7 -1 3 1 [3 -1 -3] 5 3 6 7 -3 3 1 3 [-1 -3 5] 3 6 7 -3 5 1 3 -1 [-3 5 3] 6 7 -3 5 1 3 -1 -3 [5 3 6]