首页 > 其他 > 详细

单调队列专题

时间:2014-03-11 15:23:00      阅读:525      评论:0      收藏:0      [点我收藏+]

首先得讲一下单调队列,顾名思义,单调队列就是队列中的每个元素具有单调性,如果是单调递增队列,那么每个元素都是单调递增的,反正,亦然。

那么如何对单调队列进行操作呢?

是这样的:对于单调队列而言,队首和队尾都可以进行出队操作,但只有队尾能够进行入队操作。

至于如何来维护单调队列,这里以单调递增队列为例:

1、如果队列的长度是一定的,首先判断队首元素是否在规定范围内,如果不再,则队首指针向后移动。(至于如何来判断是否在制定范围内,一般而言,我们可以给每个元素设定一个入队的序号,这样就能够知道每个元素原来的顺序了)。

2、每次加入元素是,如果元素小于队尾元素且队列非空,则减小尾指针,队尾元素出队列,直到保持队列单调性为止。

 

题目链接:http://acm.fzu.edu.cn/problem.php?pid=1894

单调队列的入门题,我们给每个队列中的元素设定一个入队序号,并且设置一个变量来记录当前有多少人离开,这样我们可以维护一个单调递减队列,每次入队的时候,找当前元素适合的位置,每次出队列的时候,判断当前队首元素的入队序号与离开总入数的大小,如果小于等于,则说明当前队首元素应该已经在出队范围内,那么队首指针应该向后移动,直到找到元素的序号比当前离开的总人数大的那个元素,并且出队列。

bubuko.com,布布扣
 1 /*************************************************************************
 2     > File Name: fzu1894.cpp
 3     > Author: syhjh
 4     > Created Time: 2014年03月11日 星期二 08时55分28秒
 5  ************************************************************************/
 6 #include <iostream>
 7 #include <cstdio>
 8 #include <cstring>
 9 #include <algorithm>
10 using namespace std;
11 
12 const int MAXN = (1000000 + 10);
13 struct Node {
14     int val, num;
15 };
16 
17 Node que[MAXN];
18 
19 int main()
20 {
21     char s1[7], s2[7];
22     int Case;
23     scanf("%d", &Case);
24     while (Case--) {
25         int head = 0, tail = -1, val;
26         int num = 0, level = 0;
27         scanf("%s", s1);
28         while (~scanf("%s", s1)) {
29             if (strcmp(s1, "END") == 0) {
30                 break;
31             }
32             if (s1[0] == C) {
33                 scanf("%s %d", s2, &val);
34                 //找到当前值适合插入的位置,并且将其后面的元素全部舍弃
35                 while (head <= tail && que[tail].val <= val) tail--;
36                 que[++tail].val = val;
37                 que[tail].num = ++num;
38             } else if (s1[0] == Q) {
39                 //level记录了有多少个离开,因此我们要找的是队头元素进队列时的序号大于
40                 //目前离开的总人数,这样才能够说明当前元素还在队列中
41                 while (head <= tail && que[head].num <= level) {
42                     head++;
43                 }
44                 if (tail < head) {
45                     puts("-1");
46                 } else 
47                     printf("%d\n", que[head].val);
48             } else 
49                 level++;
50         }
51     }
52     return 0;
53 }
View Code

 

题目链接:http://poj.org/problem?id=2823

比较裸的单调队列,可以开两个队列来保存结果,一个单调递增来保存最小值,一个单调递减来保存最大值,每个元素入队列时都给一个入队编号,然后我们在判断的时候,只要判断当前元素的序号与队首元素的序号相差不大与K,则最值就是当前队首元素,否则,队首指针向后移动,直到找到一个符合条件的元素。

bubuko.com,布布扣
 1 /*************************************************************************
 2     > File Name: poj2823.cpp
 3     > Author: syhjh
 4     > Created Time: 2014年03月11日 星期二 09时45分04秒
 5  ************************************************************************/
 6 #include <iostream>
 7 #include <cstdio>
 8 #include <cstring>
 9 #include <algorithm>
10 #include <vector>
11 using namespace std;
12 
13 const int MAXN = (1000000 + 100);
14 struct Node {
15     int val, index;
16 };
17 
18 Node que1[MAXN], que2[MAXN];
19 int N, K, M;
20 int num[MAXN];
21 int ans1[MAXN], ans2[MAXN];
22 
23 void getSolve1()
24 {
25     int head = 0, tail = -1, len = K;
26     M = 0;
27     for (int i = 1; i <= N; i++) {
28         while (head <= tail && num[i] <= que1[tail].val) {
29             tail--;
30         }
31         que1[++tail].val = num[i];
32         que1[tail].index = i;
33         if (i - len == 0) {
34             while (head <= tail && i - que1[head].index + 1 > K) {
35                 head++;
36             }
37             ans1[++M] = que1[head].val;
38             len++;
39         }
40     }
41 }
42 
43 void getSolve2()
44 {
45     int head = 0, tail = -1, len = K;
46     M = 0;
47     for (int i = 1; i <= N; i++) {
48         while (head <= tail && num[i] >= que2[tail].val) {
49             tail--;
50         }
51         que2[++tail].val = num[i];
52         que2[tail].index = i;
53         if (i - len == 0) {
54             while (head <= tail && i - que2[head].index + 1 > K) {
55                 head++;
56             }
57             ans2[++M] = que2[head].val;
58             len++;
59         }
60     }
61 }
62 
63 int main()
64 {
65     while (~scanf("%d %d", &N, &K)) {
66         for (int i = 1; i <= N; i++) {
67             scanf("%d", &num[i]);
68         }
69         getSolve1();
70         getSolve2();
71         for (int i = 1; i <= M; i++) {
72             if (i == M) printf("%d\n", ans1[i]);
73             else printf("%d ", ans1[i]);
74         }
75         for (int i = 1; i <= M; i++) {
76             if (i == M) printf("%d\n", ans2[i]);
77             else printf("%d ", ans2[i]);
78         }
79     }
80     return 0;
81 }
View Code

单调队列专题,布布扣,bubuko.com

单调队列专题

原文:http://www.cnblogs.com/wally/p/3593224.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!