POJ2823 Sliding Window (单调队列)
Sliding Window
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 by one position. Following is an example: The array is [1 3 -1 -3 5 3 6 7], and k is 3.
Your task is to determine the maximum and minimum values in the sliding window at each position. Input The input consists of two lines. The first line contains two integers n and k which are the lengths of the array and the sliding window. There are n integers in the second line.
Output There are two lines in the output. The first line gives the minimum values in the window at each position, from left to right, respectively. The second line gives the maximum values.
Sample Input 8 3 Sample Output -1 -3 -3 -3 3 3 Source POJ Monthly--2006.04.28, Ikki
|
大意:
看题目中那个表格很容易懂,就是有个滑动区间,每次我们要找到这个区间中的最大值、最小值。
题解:
单调队列。
单调队列是DP优化的一种,能实现O(VN)的多重背包。这题虽然不是DP,不过能怒用一发单调队列。
单调队列是用一个单调的队列来存储必要的元素,并不存储无用的元素。在这题的求最小值的过程中:
元素按顺序读入队列q,当队列为空时直接读入;当队列非空时,若队尾的元素不小于当前要入队的元素,则踢出队尾,直到队尾元素小于要入队的元素或者队为空为止。
再开一个数组p,存储队列中的元素在原数据中的下标。
像这样:
(读元素a[i])
while(l<r && q[r-]>=a[i]) r--;
p[r]=i;
q[r++]=a[i];
然后检查队首,如果p存储的队首的元素下标表示该元素已经滑出区间,则将其踢出,像这样:
(检查队首、踢出过期元素)
while(p[l]<i-k+) l++;///若队首的下标表示它已过期(滑出了区间),弹出队首
经过这2个操作后,q[l]就是所求的当前区间的最小值。然后i++,再进行这2个操作,就能得到下一个最小值。换一个符号就能求最大值了。
这两个操作有什么深意呢?
读取时那样的操作,保证了队列中存储了递增的最小若干个数,在队首能立即得到当前区间最小的数(若那个数已经滑出了区间,则它会被踢出),
当那个数滑出区间时能立即找到下一个最小的数。
就这两个简单的操作,用极低的复杂度,就能完成找区间滑动到每个地方的最小值/最大值!我就问你碉不碉!
代码:
#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<set>
using namespace std;
#define ll __int64
#define usint unsigned int
#define mz(array) memset(array, 0, sizeof(array))
#define minf(array) memset(array, inf, sizeof(array))
#define REP(i,n) for(int i=0;i<(n);i++)
#define FOR(i,x,n) for(int i=(x);i<=(n);i++)
#define WR(x) printf("%d ",(x))
#define FR freopen("1.in","r",stdin)
#define FW freopen("1.out","w",stdout) const int maxn=; int n,k;
int a[maxn];///存储数据
int q[maxn];///队列
int p[maxn];///存储a[i]的下标i void gankmin()
{
int i,l=,r=;///l,r为队列头尾
for(i=;i<k-;i++)///先将前k-1个入队
{
while(l<r && q[r-]>=a[i]) r--;///队列有元素时,要保证队尾小于要入队的元素,否则弹出队尾
///意义在于存储递增的最小若干个数,能立即得到当前区间最小的数,
///当那个数滑出区间时能立即找到下一个最小的数
p[r]=i; ///记录a[i]的下标
q[r++]=a[i];///a[i]加入队列
}
for(;i<n;i++)
{
while(l<r && q[r-]>=a[i]) r--;
p[r]=i;
q[r++]=a[i]; while(p[l]<i-k+) l++;///若队首的下标表示它已过期(滑出了区间),弹出队首
WR(q[l]);
}
} void gankmax()
{
int i,l=,r=;
for(i=;i<k-;i++)
{
while(l<r && q[r-]<=a[i]) r--;
p[r]=i;
q[r++]=a[i];
}
for(;i<n;i++)
{
while(l<r && q[r-]<=a[i]) r--;
p[r]=i;
q[r++]=a[i]; while(p[l]<i-k+) l++;
WR(q[l]);
}
} int main()
{
while(scanf("%d%d",&n,&k)!=EOF)
{
REP(i,n)
scanf("%d",&a[i]);
gankmin();
puts("");
gankmax();
puts("");
}
return ;
}
POJ2823 Sliding Window (单调队列)的更多相关文章
- POJ2823 Sliding Window(单调队列)
单调队列,我用deque维护.这道题不难写,我第二次写单调队列,1次AC. -------------------------------------------------------------- ...
- POJ 2823 Sliding Window + 单调队列
一.概念介绍 1. 双端队列 双端队列是一种线性表,是一种特殊的队列,遵守先进先出的原则.双端队列支持以下4种操作: (1) 从队首删除 (2) 从队尾删除 (3) 从队尾插入 (4) ...
- poj 2823 Sliding Window (单调队列入门)
/***************************************************************** 题目: Sliding Window(poj 2823) 链接: ...
- POJ 2823:Sliding Window 单调队列
Sliding Window Time Limit: 12000MS Memory Limit: 65536K Total Submissions: 48930 Accepted: 14130 ...
- POJ 2823 Sliding Window (单调队列)
单调队列 加了读入挂比不加更慢.... 而且这份代码要交c++ 有大神G++跑了700ms..... orzorzorz #include<iostream> #include<cs ...
- POJ 2823 UESTCoj 1221 Sliding Window 单调队列 经典入门题
题意:给出一个序列,求出每连续k个数字中最大的数和最小的数. 这是道单调队列裸题,直接写就行了. 本来用deque写出来后,发现在poj上硬是超时了,在discuss上看很多人也在抱怨超时的问题,据说 ...
- POJ2823 Sliding Window(单调队列)
题目要输出一个序列各个长度k的连续子序列的最大值最小值. 多次RMQ的算法也是能过的,不过单调队列O(n). 这题,队列存元素值以及元素下标,队尾出队维护单调性然后入队,队首出队保持新元素下标与队首元 ...
- [POJ2823]Sliding Window 滑动窗口(单调队列)
题意 刚学单调队列的时候做过 现在重新做一次 一个很经典的题目 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗 ...
- [POJ2823] Sliding Window 「单调队列」
我们从最简单的问题开始: 给定一个长度为N的整数数列a(i),i=0,1,...,N-1和窗长度k. 要求: f(i) = max{ a(i-k+1),a(i-k+2),..., a(i) },i ...
随机推荐
- Activiti系列:带有serviceTask的或者定时启动任务的流程部署失败的原因分析
在将两个带有serviceTask任务的流程部署到数据库的时候发现无法导入,最终分析出如下问题: 1)流程1是打算让定时启动事件可以每小时触发一次 由于原来是用 R/2015-11-01T01:00: ...
- 20145215《Java程序设计》实验一实验报告
实验一 Java开发环境的熟悉 实验内容及步骤 使用JDK编译.运行简单的Java程序 命令行下程序开发: 在命令行下建立实验目录,进入该目录后创建exp1目录 敲入以下代码: package exp ...
- Jenkins进阶系列之——06FTP publisher plugin插件下载(支持绝对路径)
注意:绝对路径用/开头 绝对路径:/root/.jenkins/jobs/test/workspace/bbb/test.war 相对路径:bbb/test.war 点我下载
- 学习笔记——Maven pom.xml配置详解
POM的全称是“ProjectObjectModel(项目对象模型)”. pom.xml详解 声明规范 <projectxmlns="http://maven.apache.org/P ...
- 开发一个简单实用的android紧急求助软件
之前女朋友一个人住,不怎么放心,想找一个紧急求助的软件,万一有什么突发情况,可以立即知道.用金山手机卫士的手机定位功能可以知道对方的位置状态,但不能主动发送求助信息,在网上了很多的APK,都是鸡肋功能 ...
- Backbone小记录
前言 这两天看了下Backbone.js的知识,大概了解了这个框架的一些知识. 写篇博客总结一下. Backbone.js是一个web端javascript的轻量级MVC框架.为什么说是轻量级呢?因为 ...
- IT男的”幸福”生活"续6
新的一年飘了一下,就过来了. 在过去的一年,大家都找到了自已的幸福吗? 时间在继续,人生得幸福.. 看了前面大家的回复,感觉挺开心的.像我们code Man,不可能总是coding.总得要一些生活调味 ...
- Android Studio之gradle的配置与介绍
1.gradle的简单介绍 Gradle是可以用于Android开发的新一代的Build System,也是Android Studio默认的build工具.其实Gradle脚本是基于一种JVM语言- ...
- css的垂直居中
请先看博客:http://www.jb51.net/css/39629.html
- ansible-2添加公钥
该文章摘自:http://www.fwqtg.net/%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E5%B7%A5%E5%85%B7ansible%E5 ...