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

来源:互联网 发布:seo赚钱培训 编辑:程序博客网 时间:2024/06/03 10:24

Sliding Window

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

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 thek 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 positionMinimum valueMaximum value[1  3  -1] -3  5  3  6  7 -13 1 [3  -1  -3] 5  3  6  7 -33 1  3 [-1  -3  5] 3  6  7 -35 1  3  -1 [-3  5  3] 6  7 -35 1  3  -1  -3 [5  3  6] 7 36 1  3  -1  -3  5 [3  6  7]37

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 integersn and k which are the lengths of the array and the sliding window. There aren 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 31 3 -1 -3 5 3 6 7

Sample Output

-1 -3 -3 -3 3 33 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             else83                 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             else91                 printf(" %d",max1[i]);92         }93 94     }95     return 0;96 }
复制代码

 

本文为个人随笔,如有不当之处,望各位大佬多多指教.若能为各位博友提供小小帮助,不胜荣幸.