博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【算法•日更•第十六期】信息奥赛一本通1597:【 例 1】滑动窗口题解
阅读量:4691 次
发布时间:2019-06-09

本文共 2405 字,大约阅读时间需要 8 分钟。

  废话不多说,直接上题:


 

 

1597:【 例 1】滑动窗口

时间限制: 1000 ms         内存限制: 524288 KB
提交数: 167     通过数: 106 

【题目描述】

原题来自:POJ 2823

给一个长度为 N 的数组,一个长为 K 的滑动窗体从最左端移至最右端,你只能看到窗口中的 K 个数,每次窗体向右移动一位,如下图:

 

窗口 最小值 最大值
[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

 

你的任务是找出窗体在各个位置时的最大值和最小值。

【输入】

第 1 行:两个整数 N 和 K;

第 2 行:N 个整数,表示数组的 N 个元素(≤2×109 );

 

【输出】

第一行为滑动窗口从左向右移动到每个位置时的最小值,每个数之间用一个空格分开;

第二行为滑动窗口从左向右移动到每个位置时的最大值,每个数之间用一个空格分开。

 

【输入样例】

8 31 3 -1 -3 5 3 6 7

【输出样例】

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

【提示】

据范围与提示:

对于 20% 的数据,KN1000

对于 50% 的数据,KN105 ;

对于 100% 的数据,KN106 。

【来源】

  这道题方法众多,小编就来一一讲解。

  方法一:打暴力

  文邹邹一点那就是模拟算法,直接在区间内查找,时间复杂度是O(nk),看起来也很高了,所以我们不能使用这种方法。

  方法二:线段树

  线段树是个好东西,可惜小编不会。

  方法三:动态规划

  这是最适合这道题的,这是单调队列优化动态规划的基本题型之一。不过时间复杂度相当低,只有O(n)。

  综上所述,小编就决定使用单调队列优化动态规划了。

  那么什么是单调队列优化动态规划呢?动态规划这个东西相比大家都很了解,那么问题就在于单调队列是什么。先回顾一下,队列就像是平时排队买饭一样,排成了一个队伍,满足先进先出(先排队的先买饭,先离开队伍),那么单调队列就不一样了,就是说队列中的每一个数要么就是递增的,要么就是递减的。

  但是这和动态规划有什么关系?

  在动态规划中,常常会遇到求最值(最大最小之类)的问题,这就和单调队列有关系了,单调队列的队首元素一定是整个队列的最大(或最小)的。

  好了,以题目为例,回归正题:

  我们如何设计状态?和最长上升子序列一个想法,我们不妨用min[i]表示以第i个数为结尾的窗口内最小元素。

  显然,我们会发现这样的情况(k=3):比如说目前队列里第一个数是3,第二个数是5,当前的数是1,那么3和5都会被弹出队列,为什么呢?因为在3和5的有生之年,一定不会成为最小的了,1已经在队列里了。

  max[i]也是如此,但要注意时刻维持队列内元素个数不超过k个。

  代码如下:

  

1 #include
2 #define size 1000000 3 using namespace std; 4 int n,k,a[size],minn[size],maxn[size],num[size],q[size]; 5 //依次表示:个数,窗口长度,每个数,最小数的数组,最大数的数组,队列元素的编号,队列元素的值 6 inline void dp_min()//窗口最小数dp 7 { 8 int head=1,tail=0;//head>tail表示空队列 9 for(int i=1;i<=n;i++)10 {11 while(num[head]
<=tail) head++;//将队列维持好数量 12 while(a[i]<=q[tail]&&head<=tail) tail--;//把不可能最小的弹出队列 13 q[++tail]=a[i];//加入队列 14 num[tail]=i;//记录元素编号 15 minn[i]=q[head];//队首元素一定是最小的 16 }17 }18 inline void dp_max()//窗口最大数dp (同上) 19 {20 int head=1,tail=0; 21 for(int i=1;i<=n;i++)22 {23 while(num[head]
<=tail) head++;24 while(a[i]>=q[tail]&&head<=tail) tail--;25 q[++tail]=a[i];26 num[tail]=i;27 maxn[i]=q[head];28 }29 }30 int main()31 {32 cin>>n>>k;33 for(int i=1;i<=n;i++)34 cin>>a[i];35 dp_min();36 dp_max();37 for(int i=1+k-1;i<=n;i++)//注意不要多输出 38 cout<
<<" ";39 cout<

转载于:https://www.cnblogs.com/TFLS-gzr/p/11212860.html

你可能感兴趣的文章
u-boot启动第一阶段
查看>>
MySQL批量SQL插入性能优化
查看>>
定义列属性:null,default,PK,auto_increment
查看>>
用户画像展示
查看>>
C#中StreamReader读取中文出现乱码
查看>>
使用BufferedReader的时候出现的问题
查看>>
linux安装图形界面
查看>>
博弈论之入门小结
查看>>
解决IE8下opacity属性失效问题,无法隐藏元素
查看>>
批处理文件中的路径问题
查看>>
hibernate出现No row with the given identifier exists问题
查看>>
为什么wait()和notify()属于Object类
查看>>
PHP 在5.1.* 和5.2.*之间 PDO数据库操作中的不同!
查看>>
导入properties时的坑
查看>>
配置NRPE的通讯
查看>>
shp系列(一)——利用C++进行shp文件的读(打开)与写(创建)开言
查看>>
匹配两个空格之间的字符。。。
查看>>
CSS 文字溢出 变成省略号 ...
查看>>
Spring事务
查看>>
java编程基础(三)流程控制语句
查看>>