单调队列

来源:互联网 发布:mac检测硬件信息 编辑:程序博客网 时间:2024/06/07 03:53

单调队列

Silver说两句

这一章相当于引入概念不会进行深度的挖掘读者根据案例题目来就可以了

题目

输入:
输入数据第一行为一整数T,表示有T组输入数据。
每组数据第一行为”START”,表示面试开始
接下来的数据中有三种情况:

序号 输入 含义 1 C NAME RP_VALUE名字为NAME的人品值为RP_VALUE的同学加入面试队伍。(名字长度不大于5,0 <= RP_VALUE <= 1,000,000,000) 2 G 排在面试队伍最前面的同学面试结束离开考场。 3 Q 主面试官John想知道当前正在接受面试的队伍中人品最高的值是多少。

最后一行为”END”,表示所有的面试结束,面试的同学们可以依次离开了。
所有参加面试的同学总人数不超过1,000,000。
输出:
对于每个询问Q,输出当前正在接受面试的队伍中人品最高的值,如果当前没有人正在接受面试则输出-1。

测试

Sample Input

2
START
C Tiny 1000000000
C Lina 0
Q
G
Q
END
START
Q
C ccQ 200
C cxw 100
Q
G
Q
C wzc 500
Q
END

Sample Output

1000000000
0
-1
200
100
500

题意分析

模拟维护人品最大值的过程,也就是单调队列维护最大值的过程。
对于单调队列的舞台:取最大/最小值最快,但是使用的前提条件就是:如果来了一个更大的值,辣么相对较小的值就没有存在的意义了。
这个题完全符合单调队列的特点和使用条件。
例如有这样的一个入队顺序(数值表示人品值):
1 2 3 5 2 4
1. 当第一个人来的时候,因为队列为空,所以直接入队。
2. 当第二个人来的时候,因为队列不空,并且2的优先值大于1,所以1就没有存在的意义了,3 现在队列里边只有一个元素:2
3. 当第三个人来的时候,因为队列不空,并且3的优先值大于2,所以2没有存在的意义了,现在队列里边只有一个元素:3
4. 当第四个人来的时候,因为队列不空,并且5的优先值大于3,所以3没有存在的意义了,现在队列里边只有一个元素:5
5. 当第五个人来的时候,因为队列不空,并且2的优先值小于2,所以直接入队列,现在队列里边有两个元素:5 2
6. 当第六个人来的时候,因为队列不空,并且4的优先值大于2,所以2就没有存在的意义了,现在队列里边有两个元素:5 4
功能代码块

if(str[0]=='C')  {      scanf("%s %d",str,&val);      while(head<=cur&&q[cur].val<val)cur--;//head表示头指针,cur表示当前指针      q[++cur].pos=cont++;      q[cur].val=val;  }  

这样,我们就模拟了一次单调队列入队的操作。那么对于没有存在意义的元素,就真的没有存在的意义了吗?答案是对的

读者可能会有这样的疑问,那么对于G操作呢?对于出队列的操作呢?总不能出队列的操作在四个人进来的时候直接把队列中唯一的元素5(同时也是单调队列维护的最大值)直接出队吧

我们可以对入队的节点编上号,然后用一个变量last表示一共有多少出队的节点数,如果q【head】.编号已经小于了这个last.,那么说明这个节点已经出队了,在Q操作的时候对应判断一下即可。

else if(str[0]=='Q')  {      while(head<=cur&&q[head].pos<last)head++;      if(head>cur)printf("-1\n");      else printf("%d\n",q[head].val);  }  else last++;//当是G操作的时候,计数器++  

总结

单调队列就是每次向队列中插入一个较大(较小)元素时,讲队尾比该元素小的元素都删去从而保证队列是一直单调递减(递增)的。由此我们可以以O(1)的时间来找到一组数据中的最大(最小)元素。因此我们可以将此思想用于所有需要求一组数据的最大(最小)值的算法中。进而将算法的复杂度由O(n^n^)下降到O(n^n-1^);