POJ2823

题目:给出n个数(n<=1000000)和k,从左到右依次求每k个数字的最大,最小值
红果果的单调队列,算是一道学习单调队列的好题了。
单调队列,名字听起来挺高大上,其实很简单。
同样用到一个普通的队列,一个头指针和一个尾指针,队列用结构体定义,包含两个成员,该元素的值和改元素在原数组中的下标。
单调队列,顾名思义,就是说这个队列里的元素是单调的,递增或递减。查询最小值是O(1),总的复杂度是O(N)这里以单调递增为例,可以求出每个k区间内的最小值。单调队列里面元素是递增的,对于每一个新入队的元素,先从队尾开始向前找第一个小于这个要入队的元素,然后把找到的这个元素后面的所有队员全部从队尾出队(将尾指针移到所找到的元素的后面一个即可),这样这个元素就入队了。对于每个区间,队头元素就是该区间的最小值。
举个单调队列的例子。
8
1 3 -1 -3 5 3 6 7
一开始,队列为空,
1 入队
3 入队,从队尾找第一个小于3的元素,即 1 ,接着将 3放到1后
-1 入队 1、3都大于 -1 所以1和3 都出队,-1 则排到了队头
-3 入队 -3 小于 -1,-1出队,-3为队头元素
5 入队,5大于-3 5排到-3后
3 入队 5出队,3排到-3后,这时队列只有两个元素 -3 和3
6 入队,3小于6 则6排到队尾3的后面
7 入队 排到队尾
其实这个东西很简单,具体看看程序想一想就理解。

 

 

 

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 using namespace std;
 5 const int maxn = 1000005;
 6 struct node
 7 {
 8     int value;
 9     int index;
10 }que[maxn];
11 int a[maxn];
12 int front,rear;
13 int main()
14 {
15     //freopen("in.txt","r",stdin);
16     int n,k;
17     while(cin>>n>>k)
18     {
19         for(int i = 1;i<=n;++i)scanf("%d",a+i);
20         front = 1;rear = 0;
21         //求最小值
22         for(int i = 1;i<k;++i)
23         {
24             //在队列非空,情况下,从队尾找小于a[i]的第一个位置
25             while(front<=rear && que[rear].value>=a[i])rear--;
26             que[++rear].value = a[i];
27             que[rear].index = i;
28         }
29         for(int i = k;i<=n;++i)
30         {   //删除队尾不需要的元素,将第k个元素入队
31             while(front<=rear && que[rear].value>=a[i])rear--;
32             que[++rear].value = a[i];
33             que[rear].index = i;
34             //维护队列的长度不超过k
35             if(que[front].index<=i-k)front++;
36             printf("%d ",que[front].value);
37         }
38         printf("\n");
39         //求最大值
40         front  =  1;rear = 0;
41         for(int i = 1;i<k;++i)
42         {
43             while(front<=rear && que[rear].value<=a[i])rear--;
44             que[++rear].value = a[i];
45             que[rear].index = i;
46         }
47         for(int i = k;i<=n;++i)
48         {
49             while(front<=rear && que[rear].value<=a[i])rear--;
50             que[++rear].value = a[i];
51             que[rear].index = i;
52             if(que[front].index<=i-k)front++;
53             printf("%d ",que[front].value);
54         }
55 
56     }
57     return 0;
58 }

 

posted on 2014-08-24 22:40  round_0  阅读(204)  评论(0编辑  收藏  举报

导航