首先得讲一下单调队列,顾名思义,单调队列就是队列中的每个元素具有单调性,如果是单调递增队列,那么每个元素都是单调递增的,反正,亦然。
那么如何对单调队列进行操作呢?
是这样的:对于单调队列而言,队首和队尾都可以进行出队操作,但只有队尾能够进行入队操作。
至于如何来维护单调队列,这里以单调递增队列为例:
1、如果队列的长度是一定的,首先判断队首元素是否在规定范围内,如果不再,则队首指针向后移动。(至于如何来判断是否在制定范围内,一般而言,我们可以给每个元素设定一个入队的序号,这样就能够知道每个元素原来的顺序了)。
2、每次加入元素是,如果元素小于队尾元素且队列非空,则减小尾指针,队尾元素出队列,直到保持队列单调性为止。
题目链接:http://acm.fzu.edu.cn/problem.php?pid=1894
单调队列的入门题,我们给每个队列中的元素设定一个入队序号,并且设置一个变量来记录当前有多少人离开,这样我们可以维护一个单调递减队列,每次入队的时候,找当前元素适合的位置,每次出队列的时候,判断当前队首元素的入队序号与离开总入数的大小,如果小于等于,则说明当前队首元素应该已经在出队范围内,那么队首指针应该向后移动,直到找到元素的序号比当前离开的总人数大的那个元素,并且出队列。
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 }