【志愿者选拔】单调队列、输入优化
题目描述
西博会马上就要开幕了,电子科技大学组织了一次志愿者选拔活动。
参加志愿者选拔的同学们排队接受面试官们的面试。参加面试的同学们按照先来先面试并且先结束的原则接受面试官们的考查。
面试中每个人的英语口语能力是主要考查对象之一。
作为主面试官的John想知道当前正在接受面试的同学队伍中口语能力值最高的是多少。于是他请你帮忙编写一个程序来计算。
输入格式
输入数据第一行为一整数 T,表示有 T(T<=5)组输入数据。
每组数据第一行为“START”,表示面试开始。
接下来的数据中有三种情况:
1 C NAME KY_VALUE 名字为 NAME 的口语能力值为 KY_VALUE 的同学加入面试队伍。
(名字长度不大于5,0<=KY_VALUE<=1,000,000,000)。
2 G 排在面试队伍最前面的同学面试结束离开考场。
3 Q 主面试官 John 想知道当前正在接受面试的队伍中口语能力最高的值是多少。
最后一行为”END”,表示所有的面试结束,面试的同学们可以依次离开了。
所有参加面试的同学总人数不超过 1,000,000。
输出格式
对于每个询问 Q,输出当前正在接受面试的队伍中口语能力最高的值,如果当前没有人正在接受面试则输出 -1。
样例数据 1
输入 [复制]
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
输出
1000000000
0
-1
200
100
500
题目分析
单调队列。维护一个能力值递增的序列,入队维护单调性并插入队尾,出队只需判断队首是不是第一个人。
本题最坑的居然不是单调队列,而是读入的优化,数据中的名字没有任何作用,如果按照字符串来读的话,每个点要跑3000+ms,所以要用read进行跳过,直接读取到数字。
code
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<algorithm> #include<cmath> #include<vector> using namespace std; const int N = 1e6 + 5; char name[16]; int val[N], fst, que[N], head, tail, T, cnt; inline int read(){ int i = 0, f = 1; char ch = getchar(); for(; (ch < '0' || ch > '9') && ch != '-'; ch = getchar()); if(ch == '-') f = -1, ch = getchar(); for(; ch >= '0' && ch <= '9'; ch = getchar()) i = (i << 3) + (i << 1) + (ch - '0'); return i * f; } inline void wr(int x){ if(x < 0) putchar('-'), x = -x; if(x > 9) wr(x / 10); putchar(x % 10 + '0'); } int main(){ //freopen("h.in", "r", stdin); T = read(); char k[10], t; while(T--){ memset(val, -1, sizeof val); memset(que, 0, sizeof que); cnt = 0; gets(k); head = 1, tail = 0; while((t = getchar()) != 'E'){ if(t == 'C'){ if(!cnt) fst = 1; cnt++; val[cnt] = read(); while(head <= tail && val[que[tail]] < val[cnt]) tail--; que[++tail] = cnt; } else if(t == 'G'){ if(que[head] == fst) head++; fst++; } else if(t == 'Q') wr(val[que[head]]), putchar('\n'); // cout<<endl<<"!!!";for(int j = head; j <= tail; j++) cout<<val[que[j]]<<" ";cout<<"!!!"<<endl; } gets(k); } return 0; }