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 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

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

分析:

这道题让我们每次输出区间内的最大值和最小值,如果每次都扫一遍复杂度较高,本题的数据比较大,这种方法时间上无法承受。本题让我们求区间最大最小值,不难想到用线段树解决这个问题,只需要每次用线段树查询区间的最大最小值即可。

核心代码如下:

查询代码:

 1 QAQ Query_Max ( int q , int w , int i )
 2 {
 3     if(q <= tr[i].l && w >= tr[i].r )return tr[i].maxtr ;
 4     else
 5     {
 6         QAQ mid = (tr[i].l + tr[i].r ) >> 1;
 7         if(q > mid)
 8         {
 9             return Query_Max ( q , w , i << 1 | 1);
10         }
11         else if(w <= mid)
12         {
13             return Query_Max ( q , w , i << 1);
14         }
15         else
16         {
17             return Max( Query_Max ( q , w , i << 1) , Query_Max ( q , w , i << 1 | 1));
18         }
19     }
20 }
21
22
23 QAQ Query_Min ( int q , int w , int i )
24 {
25     if(q <= tr[i].l && w >= tr[i].r )return tr[i].mintr ;
26     else
27     {
28         QAQ mid = (tr[i].l + tr[i].r ) >> 1;
29         if(q > mid)
30         {
31             return Query_Min ( q , w , i << 1 | 1);
32         }
33         else if(w <= mid)
34         {
35             return Query_Min ( q , w , i << 1);
36         }
37         else
38         {
39             return Min( Query_Min ( q , w , i << 1) , Query_Min ( q , w , i << 1 | 1));
40         }
41     }
42 }

注:这里QAQ就是long long 用typedef long long QAQ;定义的。

建树及Push_up操作:

 1 void Push_up (int i)
 2 {
 3     tr[i].maxtr = Max ( tr[i << 1].maxtr , tr[i << 1 | 1].maxtr);
 4     tr[i].mintr = Min ( tr[i << 1].mintr , tr[i << 1 | 1].mintr);
 5 }
 6
 7 void Build_Tree (int x , int y , int i)
 8 {
 9     tr[i].l = x ;
10     tr[i].r = y ;
11     if( x == y )tr[i].maxtr = tr[i].mintr = arr[x] ;
12     else
13     {
14         QAQ mid = (tr[i].l + tr[i].r ) >> 1 ;
15         Build_Tree ( x , mid , i << 1 );
16         Build_Tree ( mid + 1 , y , i << 1 | 1);
17         Push_up ( i );
18     }
19 }

以上就是用线段树解法,是线段树的简单应用,本题还有很多其他写法,比如维护单调队列,比线段树更容易实现代码并且代码量较少,以下是维护单调队列的代码:

 1 #include "stdio.h"
 2 #define maxn (1000100)
 3 int n, K;
 4 int Head, Tail;
 5 int val[maxn];
 6 int numb[maxn];
 7 bool Flag;
 8 inline bool cmp(int a, int b)
 9 {
10     return Flag ? a < b : a > b;
11 }
12 void Push(int idx)
13 {
14     while(Head < Tail && cmp(val[idx], val[numb[Tail - 1]])) Tail --;
15     numb[Tail++] = idx;
16     while(Head < Tail && idx - numb[Head] + 1 > K) Head ++;
17 }
18 int main()
19 {
20     scanf("%d %d", &n, &K);
21     for(int i = 1; i <= n; i++) scanf("%d", &val[i]);
22     Head = 0 , Tail = 0 , Flag = true;
23     for(int i = 1; i < K; i++) Push(i);
24     for(int i = K; i <= n; i++)
25     {
26         Push(i);
27         printf("%d ", val[numb[Head]]);
28     }
29     puts("");
30     Head = 0 , Tail = 0 , Flag = false;
31     for(int i = 1; i < K; i++) Push(i);
32     for(int i = K; i <= n; i++)
33     {
34         Push(i);
35         printf("%d ", val[numb[Head]]);
36     }
37     puts("");
38     return 0;
39 }

(完)

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~·~~~~~~~~~~~~~~

时间: 2024-10-22 07:03:10

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

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

洛谷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). 输出格式: 输出共两行,第一行为每次窗口滑动的最小值

POJ 2823 Sliding Window 【单调队列】

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

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(单调队列)

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 b

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

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