题目链接:点击查看

题目大意:给出一个由n个数构成的序列,再给出一个长度为k的窗口,这个窗口从第一个下标开始一直向后移动,每次移动一个单位,每次移动询问一次该窗口中的最大值和最小值,最后输出答案

题目分析:看似是一个模拟,其实暴力模拟肯定会爆,因为涉及到区间最值问题,而且还是静态的询问,所以这个题目有三种方法可以解决,分别是st表,线段树和单调队列,因为st表我不会优化,所以有五个测试点MLE了,这里就不用那个方法了,线段树的话空间复杂度比起st表一般是能小上5倍左右,但时间复杂度每一次查询时要多logn的常数,所以酌情考虑吧,用线段树的话就不会MLE了,擦边把这个题目给A了,一会也放一下代码,没什么好说的,主要是来说一下单调队列来做这个题目,之前只是学过单调栈,今天接触了一下单调队列,发现还是挺简单的,主要原理就是用双端队列维护一个严格递增或严格递减的序列,每次增加一个新值的时候,将其与尾部比较,最终插入尾部,当使用的时候,是使用头部的数值,大概就是这样了,一会看代码理解一下吧

然后这个题目还需要维护一下每个数值所代表的id,用来判断该数值在当前区间中是否过期,若过期的话直接舍弃掉即可

当然三种方法的复杂度来比较一下吧:

st表:空间复杂度nlogn,时间复杂度:打表nlogn,查询O(1)

线段树:空间复杂度n*4,时间复杂度:建树nlogn,查询nlogn

单调队列:空间复杂度n,时间复杂度:n

吐槽一句:这个题目本来是poj上的题目,为什么跑来洛谷做呢,三种方法,st表MLE,线段树TLE,单调队列还不支持C++11,我:????

代码:

单调队列(deque):

#include<iostream>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<cmath>
#include<cctype>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<set>
#include<map>
#include<sstream>
#include<deque>
using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=1e6+100;struct Node
{int val,id;
}a[N];int ans_max[N],ans_min[N];int main()
{
//  freopen("input.txt","r",stdin);
//  ios::sync_with_stdio(false);int n,k;while(scanf("%d%d",&n,&k)!=EOF){for(int i=1;i<=n;i++){scanf("%d",&a[i].val);a[i].id=i;}deque<Node>mmax;//维护最大值的单调队列deque<Node>mmin;//维护最小值的单调队列for(int i=1;i<=k-1;i++)//预处理1~k-1的值{while(mmax.size()&&mmax.back().val<=a[i].val)//将比当前值小的数全删掉(尾部)mmax.pop_back();mmax.push_back(a[i]);while(mmin.size()&&mmin.back().val>=a[i].val)//将比当前值大的数全删掉(尾部)mmin.pop_back();mmin.push_back(a[i]);}for(int i=k;i<=n;i++)//枚举滑动窗口的末尾位置{int left=i-k+1;//记录滑动窗口的首位置while(mmax.size()&&mmax.back().val<=a[i].val)//将比当前值小的数全删掉(尾部)mmax.pop_back();mmax.push_back(a[i]);while(mmin.size()&&mmin.back().val>=a[i].val)//将比当前值大的数全删掉(尾部)mmin.pop_back();mmin.push_back(a[i]);while(mmax.size()&&mmax.front().id<left)//将过期的值删掉(头部)mmax.pop_front();while(mmin.size()&&mmin.front().id<left)//将过期的值删掉(头部)mmin.pop_front();ans_max[left]=mmax.front().val;//更新答案ans_min[left]=mmin.front().val;}printf("%d",ans_min[1]);for(int i=2;i+k-1<=n;i++)printf(" %d",ans_min[i]);printf("\n%d",ans_max[1]);for(int i=2;i+k-1<=n;i++)printf(" %d",ans_max[i]);printf("\n");}return 0;
}

单调队列(模拟):专门给poj2823改的代码

#include<iostream>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<cmath>
#include<cctype>
#include<stack>
#include<list>
#include<vector>
#include<set>
#include<map>
#include<sstream>
using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=1e6+100;struct Node
{int val,id;
}t[N];int a[N];int main()
{
//  freopen("input.txt","r",stdin);
//  ios::sync_with_stdio(false);int n,k;while(scanf("%d%d",&n,&k)!=EOF){for(int i=1;i<=n;i++)scanf("%d",a+i);int l=1,r=0;for(int i=1;i<=n;i++){int left=i-k+1;while(l<=r&&t[l].id<left)l++;while(l<=r&&t[r].val>=a[i])r--;t[++r].val=a[i];t[r].id=i;if(i>=k)printf("%d ",t[l].val);}printf("\n");l=1,r=0;for(int i=1;i<=n;i++){int left=i-k+1;while(l<=r&&t[l].id<left)l++;while(l<=r&&t[r].val<=a[i])r--;t[++r].val=a[i];t[r].id=i;if(i>=k)printf("%d ",t[l].val);}printf("\n");}return 0;
}

线段树:

#include<iostream>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<cmath>
#include<cctype>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<set>
#include<map>
#include<sstream>
using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=1e6+100;int ans1[N],ans2[N];struct Node
{int l,r,mmax,mmin;
}tree[N<<2];void build(int k,int l,int r)
{tree[k].l=l;tree[k].r=r;if(l==r){scanf("%d",&tree[k].mmin);tree[k].mmax=tree[k].mmin;return;}int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);tree[k].mmax=max(tree[k<<1].mmax,tree[k<<1|1].mmax);tree[k].mmin=min(tree[k<<1].mmin,tree[k<<1|1].mmin);
}int query_max(int k,int l,int r)
{if(tree[k].r<l||tree[k].l>r)return -inf;if(tree[k].r<=r&&tree[k].l>=l)return tree[k].mmax;return max(query_max(k<<1,l,r),query_max(k<<1|1,l,r));
}int query_min(int k,int l,int r)
{if(tree[k].r<l||tree[k].l>r)return inf;if(tree[k].r<=r&&tree[k].l>=l)return tree[k].mmin;return min(query_min(k<<1,l,r),query_min(k<<1|1,l,r));
}int main()
{
//  freopen("input.txt","r",stdin);
//  ios::sync_with_stdio(false);int n,k;while(scanf("%d%d",&n,&k)!=EOF){build(1,1,n);for(int i=1;i+k-1<=n;i++){ans1[i]=query_min(1,i,i+k-1);ans2[i]=query_max(1,i,i+k-1);}printf("%d",ans1[1]);for(int i=2;i+k-1<=n;i++)printf(" %d",ans1[i]);printf("\n%d",ans2[1]);for(int i=2;i+k-1<=n;i++)printf(" %d",ans2[i]);printf("\n");}return 0;
}

洛谷 - P1886 滑动窗口(单调队列/线段树)相关推荐

  1. 洛谷 P1886 滑动窗口

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

  2. 入门经典_Chap08_题解总结:极角扫描法 滑动窗口 单调队列 单调栈

    总结  本章主要关注一个重要的问题 – 单调队列和单调栈的使用  同时还有一些其他的问题,如扫描法,递归的思想, 构造, 分治, 二分等 知识点 单调队列 和 单调栈 题目 UVA - 1606 Am ...

  3. 【洛谷 P1638】 【单调队列】 逛画展

    [洛谷 P1638] [单调队列] 逛画展 题目 解题思路 先求出最前面囊括所有画的位置 然后如果左边界的画不止存在一次,左边界右移 不断扩展右边界,求取答案 代码 #include<iostr ...

  4. [USACO18JAN]Lifeguards P 洛谷黑题,单调队列优化DP

    传送门:戳我 这道题有两个版本,S和P,S是K等于1的情况,显然可以用线段树水过. P版本就难了很多,洛谷黑题(NOI/NOI+/CTSC),嘿嘿. 我自己也不是很理解,照着题解写了一遍,然后悟到了一 ...

  5. 滑动窗口--单调队列

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

  6. 力扣1438——绝对差不超过限制的最长连续子数组(滑动窗口+单调队列)

    题目描述(中等) 给你一个整数数组 nums ,和一个表示限制的整数 limit,请你返回最长连续子数组的长度,该子数组中的任意两个元素之间的绝对差必须小于或者等于 limit . 如果不存在满足条件 ...

  7. POJ2823 滑动窗口 单调队列模板题 第一次用了发函数指针

    题意 有一个n长的序列,用k长的窗口在上面滑动,去每次窗口中最小和最大的数. 思路 使用单调队列,维护这个队列是单调的.以取最小元素为例,若窗口内左边元素>=右边元素,则左边元素失去保留的意义, ...

  8. 【洛谷】【动态规划+单调队列】P1725 琪露诺

    [题目描述:] 在幻想乡,琪露诺是以笨蛋闻名的冰之妖精. 某一天,琪露诺又在玩速冻青蛙,就是用冰把青蛙瞬间冻起来.但是这只青蛙比以往的要聪明许多,在琪露诺来之前就已经跑到了河的对岸.于是琪露诺决定到河 ...

  9. 洛谷 - P1714 切蛋糕(单调队列+前缀和+思维)

    题目链接:点击查看 题目大意:给出一个由n个数组成的序列,求长度不超过m的连续子段和中的最大值 题目分析:因为给出了一个限制条件,所以这就不能当普通的动态规划来做了,我们可以跑一遍前缀和,然后枚举每一 ...

最新文章

  1. mysql 中模糊查询的四种用法介绍
  2. 树莓派:3安装NodeJS
  3. ruby中的self
  4. dp之二维背包poj1837(天平问题 推荐)
  5. 选redis还是memcache,源码怎么说?
  6. python查找excel中字符串_在Python问题中通过Excel搜索字符串/正则表达式
  7. oracle服务器支持ipmi带外管理,ipmi带外管理
  8. 【ML】理解偏差和方差,过拟合和欠拟合
  9. php和app关系,php在app开发中的应用
  10. C语言程序100例之C#版-019
  11. 印尼Widya Robotics携手华为云,让建筑工地安全看得见
  12. mac adb环境变量配置
  13. 读《如何找对另一半》后感以及论自己择偶标准
  14. python 等差数列_413. 等差数列划分(Python)
  15. Android Studio导入第三方sdk
  16. 机器视觉运动控制一体机应用例程|锂电池组装线上的读码应用
  17. python学了没有用_如何用Python进行无监督学习
  18. md文件打开错误(Failed to load file)
  19. send/sendto和recv/recvfrom各自的区别
  20. LabVIEW控制Arduino实现示波器(基础篇—7)

热门文章

  1. Nacos-服务多级存储模型
  2. Nginx跨域问题的案例演示
  3. 高仿真的类-ApplicationContextAware
  4. Spring MVC 源码-初始化阶段
  5. 再述Spring AOP 应用场景
  6. Redis基本数据类型
  7. ClassLoader的常用方法及获取方法
  8. 登陆状态购物车数据结构
  9. 部署RocketMQ的管理工具
  10. 约束rmq_差分约束