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 ...
随机推荐
- LeetCode:Binary Tree Level Order Traversal I II
LeetCode:Binary Tree Level Order Traversal Given a binary tree, return the level order traversal of ...
- Linux第14周学习笔记
虚拟存储器 虚拟存储器是硬件异常.硬件地址翻译.主存.磁盘文件和内核软件的完美交互. 虚拟存储器的特点: 中心的 强大的 危险的 物理和虚拟寻址 计算机系统的主存被组织成一个由M个连续的字节大小的单元 ...
- 20135316王剑桥 linux第二周课实验笔记
Linux中命令格式为: command [options选项] [arguments参数] //中括号代表是可选的,即有些命令不需要选项也不需要参数 ls或ls .显示是当前目录的内容,这里“.”就 ...
- JS闭包那些事
关于闭包,我曾经一直觉得它很讨厌,因为它一直让我很难搞,不过有句话怎么说来着,叫做你越想要一个东西,就要装作看不起它的样子.所以,抱着这个态度,我终于掳获了闭包. 首先来认识一下什么是闭包,闭包,一共 ...
- JAVA中的NIO(一)
1.IO与NIO IO就是普通的IO,或者说原生的IO.特点:阻塞式.内部无缓冲,面向流. NIO就是NEW IO,比原生的IO要高效.特点:非阻塞.内部有缓存,面向缓冲. 要实现高效的IO操作,尤其 ...
- 小记:Quartz StartNow() 无效
今天遇到一个问题,调度器在启动时无法立刻开始执行任务,代码如下: var trigger = TriggerBuilder.Create() .StartNow() //此处无效 .WithCronS ...
- Symfony启动过程详细学习
想了解symfony的启动过程,必须从启动文件(这里就以开发者模式)开始. <?php /* * web/app_dev.php */ $loader = require_once __DIR_ ...
- JDO持久 (jdbc ejb)
转自:http://blog.csdn.net/liuzhigang1237/article/details/6305113 JDO快速入门 Java数据对象(Java Data Objects,JD ...
- Codeforces Round #167 (Div. 2) D. Dima and Two Sequences 排列组合
题目链接: http://codeforces.com/problemset/problem/272/D D. Dima and Two Sequences time limit per test2 ...
- jsp+oracle实现数据库内容以表格形式在前台显示(包含分页)
jsp+oracle实现数据库内容以表格形式在前台显示(包含分页) 在文件夹内新增list_emp.jsp 代码如下: <%@ page contentType="text/html& ...