http://acm.fzu.edu.cn/problem.php?pid=1894
Problem 1894 志愿者选拔
Accept: 768 Submit: 2521
Time Limit: 1500 mSec Memory Limit : 32768 KB
Problem Description
Input
输入 | 含义 | |
1 | C NAME RP_VALUE | 名字为NAME的人品值为RP_VALUE的同学加入面试队伍。(名字长度不大于5,0 <= RP_VALUE <= 1,000,000,000) |
2 | G | 排在面试队伍最前面的同学面试结束离开考场。 |
3 | Q | 主面试官John想知道当前正在接受面试的队伍中人品最高的值是多少。 |
Output
Sample Input
2STARTC Tiny 1000000000C Lina 0QGQENDSTARTQC ccQ 200C cxw 100QGQC wzc 500QEND
Sample Output
10000000000-1200100500
Hint
数据较大建议使用scanf,printf 不推荐使用STL/*fzu 1894*/
/*一个rp队列正常记录数据进出,用队首和队尾指针完成, 另一个队列pos为单调队列,
pos按顺序存放rp队列最大值到最小值(或反过来)在rp中的位置,为单调队列*/
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn= 1000010;
int rp[maxn], pos[maxn], pst, ped, rpst, rped;
//pst 单调队列队首 ped单调队列队尾 rpst 队列中数据的队首 rped 队列中数据的队尾
int bsearch(int x, int lef, int rig){ //二分查找第一个比此新加入的数x小的数在单调队列pos中的位置
int mid;
while( lef <= rig){
mid= (lef + rig)>>1;
if( rp[pos[mid]] > x) lef= mid+ 1;//注意pos为左大右小
else if( rp[pos[mid]] < x) rig= mid - 1;
else return mid + 1;
}
if( rp[pos[mid]] >= x) mid++;
return mid;
}
int main(){
// freopen("1.txt", "r", stdin);
int i, j, k ,aa, bb, T;
char tmp[10];
scanf("%d", &T);
while( T--){
scanf("%*s");
pst= ped= rpst= rped= 0;
while( 1){
scanf("%s", tmp);
if( strcmp(tmp, "END") == 0) break;
if( tmp[0]== 'C'){
scanf("%*s%d", &aa);
rp[rped]= aa; //在rp队列队尾加入新数据
if( ped== 0){
pos[0]= rped;
ped++;
}
else{
bb= bsearch(aa, pst, ped-1);
pos[bb]= rped; //新加入的数aa,在单调队列中查询到的位置bb为原rp队列中,
//第一个比新数据小的数在pos中的位置,即aa应放入在pos的哪个位置
ped= bb; //由于加了此数aa,rp队列中比次数进入早的比aa小的数都不可能再出现,
//即pos中排在bb后面的rp位置数不可能再出现,故后面的数都可在单调队列中舍弃不再考虑
//所以单调队列队尾更新至bb+1(ped为下一值的位置)
}
rped++; //rp队列新加入了值,rped++;
}
else if( tmp[0]=='Q'){
if( ped== pst){ //ped为下一值位置,所以当ped== pst时,单调队列为空
printf("-1\n");
}
else{
printf("%d\n", rp[pos[pst]]); //pst为目前rp队列中最大值在pos中位置
}
}
else {
if( rpst== pos[pst]){ //当所删除的值为当前最大值时,pos与rp队列的队首指针都要后移一位
rpst++;
pst++;
}
else rpst++;
}
}
}
return 0;
}