FZU - 1894选拔志愿者【单调队列】

来源:互联网 发布:ubuntu磁盘一直不足 编辑:程序博客网 时间:2024/05/01 16:19

Description

世博会马上就要开幕了,福州大学组织了一次志愿者选拔活动。
参加志愿者选拔的同学们排队接受面试官们的面试。参加面试的同学们按照先来先面试并且先结束的原则接受面试官们的考查。
面试中每个人的人品是主要考查对象之一。(提高人品的方法有扶老奶奶过街,不闯红灯等)
作为主面试官的John想知道当前正在接受面试的同学队伍中人品值最高的是多少。于是他请你帮忙编写一个程序来计算。

Input

输入数据第一行为一整数T,表示有T组输入数据。
每组数据第一行为”START”,表示面试开始
接下来的数据中有三种情况:
 输入含义1C NAME RP_VALUE名字为NAME的人品值为RP_VALUE的同学加入面试队伍。(名字长度不大于5,0 <= RP_VALUE <= 1,000,000,000)2G排在面试队伍最前面的同学面试结束离开考场。3Q主面试官John想知道当前正在接受面试的队伍中人品最高的值是多少。
最后一行为”END”,表示所有的面试结束,面试的同学们可以依次离开了。
所有参加面试的同学总人数不超过1,000,000

Output

对于每个询问Q,输出当前正在接受面试的队伍中人品最高的值,如果当前没有人正在接受面试则输出-1。

Sample Input

2STARTC Tiny 1000000000C Lina 0QGQENDSTARTQC ccQ 200C cxw 100QGQC wzc 500QEND

Sample Output

10000000000-1200100500

Hint

数据较大建议使用scanf,printf 不推荐使用STL

在学习单调队列优化DP之前有必要学习单调队列是什么东西@。@ 本题实现了插入数据、询问最大值、删除队首元素(题中排队的队首,不是维护队列的队首)的功能,智商捉急的我从早上看到现在才明白==

维护的队列队首是L,队尾是R,每插入一个数据,都使得队列单调递减(因为这题要求最大值,求最小值的话就单调递增呗),具体做法考虑是先假设在一个已经维护好的队列上插入,从后往前遍历队列,遇到比待插入数据小的替换,队列后面的部分截掉;

再说查询,很明显取队首元素,但是需要判断队首是否还在233333;

纠结了好半天的是删除最先来的out是啥意思,写了数据模拟才明白。我们首先得知道维护的队列有一个特殊性质:如果有一个后来的元素插进去了,那么之前序号比他小、值也比他小的就被截断舍弃了,虽然他们没有被移除出实际排的队伍,但是由于对于我们取最大值没有必要,我们不用再去维护他。。再说这个题, out小于队列首元素序号的时候,说明删掉的是我们已经放弃维护的对象,反正对于最大值的维护也没有必要,删了就删了,但是需要++out;当out>队首元素时,才有必要真的把队首元素移除,根据手工模拟队列的思想,l++即可

/**************************FZU - 18942016.2.2389241015GNU C++68716 sec ago***************************/#include<cstdio>#include<iostream>using namespace std;const int mm=1111111;int rp[mm],q[mm];char name[10],op[10];int main(){  //  freopen("cin.txt","r",stdin);    int t;    scanf("%d",&t);    while(t--)    {        int l=0,n=0,out=0,r=-1;        while(scanf("%s",op),op[0]!='E')        {            if(op[0]=='C')            {                ++n;                scanf("%s%d",name,&rp[n]);//取地址符能忘写!                while(l<=r&&rp[q[r]]<rp[n]) r--;                q[++r]=n;            }            if(op[0]=='G') (++out>=q[l])?l++:l;            if(op[0]=='Q') printf("%d\n",out<n?rp[q[l]]:-1);//队列可能空!!        }    }    return 0;}


0 0
原创粉丝点击