POJ--2823--Sliding Window----单调队列问题

Sliding Window

Time Limit:12000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u

Description

An array of size n ≤ 10 6 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題意 :  给定一个数字序列,与每次所能看见的序列长度m即窗户长度,从左向右依次移动窗户,输出每次所能看到的序列长度的最大值与最小值,直到序列结束.思路:  以求最小值为例,  1.构造递增的单调队列,即队尾元素需要小于当前元素,否则队尾元素出队.  2.首先,将前 m-1 个元素按照单调队列原则进队,并记录队列中的每个元素在数组中的下标;   其次,将剩余的元素依次进队,以 第i元素为例子,将第i元素与队尾比较,若是小于队尾,则队尾出队,否则当前元素进队,此时队列是单调递增有序的,   再之,将队头元素的下标与当前元素的下标比较,若 当前元素下标 - 队头元素下标<=m-1,则队头元素便为最小值,否则队头出队.  3.将剩余元素依次进行步骤2,便得到所求的所有最小值,求最大值亦然.AC代码分析 (请用C++提交,否则Time Limit Exceeded):
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <cmath>
 6 #include <vector>
 7 #include <map>
 8 #include<string.h>
 9 #include<stack>
10 #include<set>
11 #include <queue>
12 using namespace std;
13 int a[1000005];
14 //队列中各元素的下标
15 int p[1000005];
16 //各个区间的最大值
17 int max1[1000005];
18 //各个区间的最小值
19 int min1[1000005];
20 //数组模拟递增队列
21 int qmax[1000005];
22 //数组模拟递减队列
23 int qmin[1000005];
24 //队头,队尾
25 int head,tail;
26 int main()
27 {
28     int n,m,i,t;
29     while(~scanf("%d%d",&n,&m))
30     {
31         for( i = 1; i<=n; i++) scanf("%d",a+i);
32         //队头队尾初始化
33         head = 1;
34         tail = 0;
35         t = 1;
36         //前m-1个元素进队列
37         for( i = 1; i<=m-1; i++)
38         {
39             while(head<=tail&&qmin[tail]>=a[i]) tail--;
40             qmin[++tail] = a[i];
41             //队列中各元素的下标
42             p[tail] = i;
43
44         }
45         //求所有的最小值
46         for(; i<=n; i++)
47         {
48             //进队
49             while(head<=tail&&qmin[tail]>=a[i]) tail--;
50             qmin[++tail] = a[i];
51             p[tail] = i;
52             //判断对头是否在当前范围内
53             while(i-p[head]>m-1)
54                 head++;
55             min1[t++] = qmin[head];
56         }
57         head = 1;
58         tail = 0;
59         t = 1;
60         //求所有的最大值
61         for( i = 1; i<=m-1; i++)
62         {
63             while(head<=tail&&qmax[tail]<=a[i]) tail--;
64             qmax[++tail] = a[i];
65             p[tail] = i;
66         }
67         for(; i<=n; i++)
68         {
69             //进队
70             while(head<=tail&&qmax[tail]<=a[i]) tail--;
71             qmax[++tail] = a[i];
72             p[tail] = i;
73             //判断对头是否在当前范围内
74             while(i-p[head]>m-1)
75                 head++;
76             max1[t++] = qmax[head];
77         }
78         for( i = 1; i<t; i++)
79         {
80             if(i == 1)
81                 printf("%d",min1[i]);
82             else
83                 printf(" %d",min1[i]);
84         }
85         printf("\n");
86         for( i = 1; i<t; i++)
87         {
88             if(i == 1)
89                 printf("%d",max1[i]);
90             else
91                 printf(" %d",max1[i]);
92         }
93
94     }
95     return 0;
96 }
本文为个人随笔,如有不当之处,望各位大佬多多指教.若能为各位博友提供小小帮助,不胜荣幸.
时间: 2024-10-28 19:52:17

POJ--2823--Sliding Window----单调队列问题的相关文章

POJ 2823 Sliding Window 单调队列题解

本题是单调队列题解的入门,当然也可以使用RMQ 和 线段树,不过速度都没有单调队列那么快. 单调队列难点: 1 如何入列,保存数据 -- 最小单调队列的时候, 所有数都入列一次,在新的数据准备入列的时候,增加判断,如果当前数值小于队尾数值,那么队尾数值就出列.空队列的时候直接入列. 2 保存的数列是什么样的? 举例吧: 1 3 -1 -3 5 3 6 7 构建最小单调队列 第一个数值1的时候,空队列,那么入列,得到: 1 第二个数值3, 因为大于1:那么1不用出列,直接入列,得到: 1 3 第三

poj 2823 Sliding Window 单调队列或线段树

题目链接:http://poj.org/problem?id=2823 Sliding Window Time Limit: 12000MS   Memory Limit: 65536K Total Submissions: 38315   Accepted: 11350 Case Time Limit: 5000MS Description An array of size n ≤ 106 is given to you. There is a sliding window of size k

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

1 /***************************************************************** 2 题目: Sliding Window(poj 2823) 3 链接: http://poj.org/problem?id=2823 4 题意: 给一个数列,找所有连续k个数的最小值和最大值. 5 算法: 单调队列(入门) 6 ******************************************************************

poj 2823 Sliding Window (单调队列)

Sliding Window Time Limit: 12000MS   Memory Limit: 65536K Total Submissions: 46705   Accepted: 13485 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

poj 2823 Sliding Window

poj 2823 Sliding Window 单调队列 单调队列是一个单调的状态(递增,或者递减) 所以需要维护这么一个状态 http://baike.baidu.com/link?url=ZcGM7Hzo8zVQUU6Oqqq18SlCMJ92ts3I1aXwQGDZw_NiDDlzIIV9GKlfs3X1fcHVppZHOU31geHZG4cOcRZOAK 固定 k 区间的单调 队列,求 最小值,如果 两个元素 A B ,如果 A 的 下标 比 B 小,但是 A 的 值 比 B 大,那么在

[ACM] poj 2823 Sliding Window(单调队列)

Sliding Window Time Limit: 12000MS   Memory Limit: 65536K Total Submissions: 36212   Accepted: 10723 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

[ACM] poj 2823 Sliding Window (单调队列)

高一时,学校组织去韶山游玩,我没去,这次趁着五一,总算去了我心心念念的韶山.其实我知道所有的景点都是差不多的,可是因为电视剧<恰同学少年>,让我对毛泽东有了进一层的了解,所以,我一直都想去看看. 有两个同学一男一女是我理想的旅友,可是女生不想去,而男士回家了.所以,我独自一人去了. 准备工作:一小包饼干,一小包山楂片,两个苹果,一瓶水,帽子(防晒),墨镜(装酷) 早晨5:30起床了,洗漱完毕,吃完早餐,赶到公交车站牌那里,才6点过几分.公交车6:31才到,等了近半个小时(公交车上明明说是6:0

POJ 2823 Sliding Window 【单调队列】

题目链接:http://poj.org/problem?id=2823 题目大意:给出一组数,一个固定大小的窗口在这个数组上滑动,要求出每次滑动该窗口内的最大值和最小值. 这就是典型的单调队列,单调队列的作用就在此.单调队列的队首为区间内的最值,但是整个队列不用保持单调. 用两个队列分别处理最大值和最小值,在此说明一下最大值: 往队列中添加值num时,从队尾开始扫,直到遇到一个小于num的d值,将num插入d的后一位.之后的元素全部无效化(不管后面的元素就行).查找最大值的时候,从队首开始找,如

POJ 2823 Sliding Window 题解

POJ 2823 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 slidi

洛谷P1886 滑动窗口(POJ.2823 Sliding Window)(区间最值)

To 洛谷.1886 滑动窗口 To POJ.2823 Sliding Window 题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. 例如: The array is [1 3 -1 -3 5 3 6 7], and k = 3. 输入输出格式 输入格式: 输入一共有两行,第一行为n,k. 第二行为n个数(<INT_MAX). 输出格式: 输出共两行,第一行为每次窗口滑动的最小值