Time Limit: 12000MS | Memory Limit: 65536K | |
Total Submissions: 39404 | Accepted: 11680 | |
Case Time Limit: 5000MS |
Description
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
Output
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
单调队列,顾名思义就是具有单调性的队列O(∩_∩)O~,一般的队列只能从队尾入队、队首出队;为了保持单调队列的单调性,单调队列除具有这两种性质外,还可以从队尾出队。
以单增的单调队列为例,当元素t要入队时,先要从队尾依次弹出所有>=t的元素,再将t加在队尾。
举个例子,如果序列:1 3 -1 -3 10要构成单调队列,
先将元素“1”放入队列中,以初始化队列,
接着元素“3”要入队,队尾元素“1”比“3”小,因此“3”可以直接入队,队列变为1 3,
接着“-1”要入队,从队尾依次弹出元素“3”“1”后将“-1”入队,队列变为-1,
同理“-3”入队后,队列变为-3,
“10”入队后,队列变为-3 10
单调队列有什么用呢?看一道例题:(poj2823)
给定含有n个元素的无序序列a[],和一个整数k,要求求出a[]中每连续k个元素组成的序列中的最小值(或最大值),这样的值可能有1个或n-k+1个。
比较简单的方式,是每次都将k个数排序后输出最值,具有O(N^2logN)的时间复杂度。但如果用单调队列的话,我们可以在O(N)的时间内求解,原因是每个元素最多入队一次、出队一次。
要解决该题,我们还要记录每个元素在原序列中的位置p,每次只需从队首开始找到跟当前元素a[i]距离不大于k的元素(即是i-p+1<=k)输出即可。
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 struct node 5 { 6 int p; 7 int num; 8 }q[1000005],q1[1000005]; 9 int r,f,g,ff; 10 int a[1000005]; 11 void inquene(int i) 12 { 13 while(q[--r].num>a[i]&&r>=f); 14 // printf("r1=%d\n",r); 15 q[++r].p=i; 16 // printf("r2=%d\n",r); 17 q[r].num=a[i]; 18 r++; 19 // printf("r3=%d\n",r); 20 } 21 void dequene(int i) 22 { 23 while(q1[--g].num<a[i]&&g>=ff); 24 q1[++g].p=i; 25 q1[g].num=a[i]; 26 g++; 27 } 28 int main() 29 { 30 int n,k,i; 31 while(~scanf("%d%d",&n,&k)) 32 { 33 for(i=1;i<=n;i++) 34 scanf("%d",&a[i]); 35 r=g=2;f=ff=1; 36 q[1].p=1; 37 q[1].num=a[1]; 38 for(i=2;i<=k&&i<=n;i++) 39 { 40 inquene(i); 41 } 42 printf("%d",q[f].num); 43 for(;i<=n;i++) 44 { 45 inquene(i); 46 while(i-q[f].p>=k) 47 f++; 48 // printf("f=%d\n",f); 49 printf(" %d",q[f].num); 50 } 51 printf("\n"); 52 q1[1].p=1; 53 q1[1].num=a[1]; 54 for(i=2;i<=k&&i<=n;i++) 55 { 56 dequene(i); 57 } 58 printf("%d",q1[ff].num); 59 for(;i<=n;i++) 60 { 61 dequene(i); 62 while(i-q1[ff].p>=k) 63 ff++; 64 // printf("f=%d\n",f); 65 printf(" %d",q1[ff].num); 66 } 67 printf("\n"); 68 } 69 return 0; 70 }