Problem 1894 志愿者选拔
Accept: 1291 Submit: 4070
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
这里模仿了别人两种写法
第一种比较好理解
可以用一个双端队列q来维护这个最值,q里面只保存可能是最值的元素(位置,值)。
对于一个进队操作,我们将它从队尾开始插入,比较队尾元素和当前插入元素,
如果当前元素的值优于队尾元素,显然队尾元素在任何时刻都不可能是最值元素,
我们可以将它删除。重复这个过程直至队尾元素优于当前元素或队列为空。
对于出队操作,我们只需要从队首元素开始枚举,如果队首元素的位置已经出队,
则将其删除,依次处理,这样我们双端队列里面的元素E(place,value)
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 1000001
struct node
{
int rp;
int n;
}q[maxn];
int main()
{
int t;
char str[10];
int i,j;
cin>>t;
while(t-- && scanf("%s",str))
{
for(i=0;i<maxn;i++)
q[i].rp=-1;
int a=-1,i=0,now=0,top=0;
while(scanf("%s",str))
{
if(str[0]=='E')
break;
if(str[0]=='C')
{
int temp;
scanf("%s %d",str,&temp);
while(a>=top && q[a].rp<temp)
a--;
q[a+1].rp=temp;
q[a+1].n=i;
a++;
i++;
}
else if(str[0]=='G')
{
if(now<=i)
{
if(q[top].n==now)
top++;
now++;
}
}
else
{
if(top<=a)
printf("%d\n",q[top].rp);
else
puts("-1");
}
}
}
return 0;
}
另外一种就是模板式的单调队列
#include<stdio.h>
#include<string.h>
#define maxn 1000000
struct que{
int x,val;
que(int xx,int yy):x(xx),val(yy){}
que(){};
}q[maxn];
int main()
{
int t;
char name[6],na[10];
int rp;
scanf("%d",&t);
while(t--)
{
int i,j,k,head=0,tail=-1,leave=0,K=1;
scanf("%*s");
while(scanf("%s",name)!=EOF)
{
if(strcmp(name,"END")==0) break;
if(name[0]=='C')
{
scanf("%s%d",na,&rp);
while(tail>=head&&q[tail].val<=rp) tail--;
que now(K++,rp);
q[++tail]=now;
}
else if(name[0]=='Q')
{
while(tail>=head&&q[head].x<=leave) head++;
if(tail>=head) printf("%d\n",q[head].val);
else printf("-1\n");
}
else leave++;
}
}
return 0;
}