POJ2823

Sliding Window
Time Limit: 12000MS   Memory Limit: 65536K
Total Submissions: 38342   Accepted: 11359
Case Time Limit: 5000MS

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.

Window position Minimum value Maximum 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 -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

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
1 3 -1 -3 5 3 6 7

Sample Output

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

Source

大意:

看题目中那个表格很容易懂,就是有个滑动区间,每次我们要找到这个区间中的最大值、最小值。

题解:

单调队列

单调队列是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 (单调队列)的更多相关文章

  1. POJ2823 Sliding Window(单调队列)

    单调队列,我用deque维护.这道题不难写,我第二次写单调队列,1次AC. -------------------------------------------------------------- ...

  2. POJ 2823 Sliding Window + 单调队列

    一.概念介绍 1. 双端队列 双端队列是一种线性表,是一种特殊的队列,遵守先进先出的原则.双端队列支持以下4种操作: (1)   从队首删除 (2)   从队尾删除 (3)   从队尾插入 (4)   ...

  3. poj 2823 Sliding Window (单调队列入门)

    /***************************************************************** 题目: Sliding Window(poj 2823) 链接: ...

  4. POJ 2823:Sliding Window 单调队列

    Sliding Window Time Limit: 12000MS   Memory Limit: 65536K Total Submissions: 48930   Accepted: 14130 ...

  5. POJ 2823 Sliding Window (单调队列)

    单调队列 加了读入挂比不加更慢.... 而且这份代码要交c++ 有大神G++跑了700ms..... orzorzorz #include<iostream> #include<cs ...

  6. POJ 2823 UESTCoj 1221 Sliding Window 单调队列 经典入门题

    题意:给出一个序列,求出每连续k个数字中最大的数和最小的数. 这是道单调队列裸题,直接写就行了. 本来用deque写出来后,发现在poj上硬是超时了,在discuss上看很多人也在抱怨超时的问题,据说 ...

  7. POJ2823 Sliding Window(单调队列)

    题目要输出一个序列各个长度k的连续子序列的最大值最小值. 多次RMQ的算法也是能过的,不过单调队列O(n). 这题,队列存元素值以及元素下标,队尾出队维护单调性然后入队,队首出队保持新元素下标与队首元 ...

  8. [POJ2823]Sliding Window 滑动窗口(单调队列)

    题意 刚学单调队列的时候做过 现在重新做一次 一个很经典的题目 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗 ...

  9. [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 ...

随机推荐

  1. [CareerCup] 2.3 Delete Node in a Linked List 删除链表的节点

    2.3 Implement an algorithm to delete a node in the middle of a singly linked list, given only access ...

  2. leetcode总结:permutations, permutations II, next permutation, permutation sequence

    Next Permutation: Implement next permutation, which rearranges numbers into the lexicographically ne ...

  3. 用virtualenv管理python3运行环境

    1. 简介 virtualenv可以用来管理互不干扰的独立python虚拟环境,在有些场景下非常有用,例如: 你有两个python项目,一个是python2.7的,另一个是python3的,可以创建两 ...

  4. pythonchallenge(三)

    PythonChallenge_3 一.实验说明 1. 环境登录 无需密码自动登录,系统用户名shiyanlou,密码shiyanlou 2. 环境介绍 本实验环境采用带桌面的Ubuntu Linux ...

  5. 20145222黄亚奇《Java程序设计》实验四实验报告

    20145222<Java程序设计>第四次实验报告 实验四 Android环境搭建 实验内容 1.搭建Android环境 2.运行Android 3.修改代码,能输出学号 实验步骤 搭建A ...

  6. selection伪元素小解

    上一篇:<RGBA与Opacity区别小解> p{font-size:14px;} 今天说一个简单的伪元素::selection,它的用武之地仅在于改变选中文本时文本的颜色和文本背景颜色. ...

  7. Bootstrap系列 -- 22. 按钮详解

    Bootstrap框架首先通过基础类名“.btn”定义了一个基础的按钮风格,然后通过“.btn-default”定义了一个默认的按钮风格.默认按钮的风格就是在基础按钮的风格的基础上修改了按钮的背景颜色 ...

  8. Object C学习笔记14-分类(category)

    在.NET中有一个非常带劲的特性,那就是扩展方法. 扩展方法使你能够向现有类型“添加”方法(包括你自定义的类型和对象噢),而无需创建新的派生类型.重新编译或以其他方式修改原始类型.扩展方法是一种特殊的 ...

  9. 我为什么期待M#?

    前段时间的报导"微软将推新编程语言M#:系统编程级别的C#",第一眼看到并没有当初看到F#的那一种不安,反而感到欣喜,业界一直存在"语言论"讨论c#.java. ...

  10. 第三十课:JSDeferred详解1

    本课难度非常大,看一遍,蛋会疼,第二遍蛋不舒服,第三遍应该貌似懂了.初学者莫来,没必要,这完全就是一个研究. JSDeferred是日本高手cho45搞出来的,其易用性远胜于Mochikit Defe ...