写这篇题解前重复一句被很多人说过的话...."一直以为单调队列就是优先队列, 2了....."
然后这题开始用priority_queue, 悲催地TLE了...
科普:
1/ 优先队列, 一般用堆实现, 就是STL里priority_queue那玩意...也就是优化dijkstra时用的那玩意....
用处: 从一堆数里用O(1)的时间找到最优值, 用O(logn)的时间插入.删除最优值等.
2/ 单调队列, 有叫双端队列, 即传说中的deque....它的特点是能够O(1)地在头尾插入或删除.
用处: deque本身是没有任何单调可言的, 但是我们在从尾部插入新数据的时候, 为了维护队列单调性质, 可言从尾部先pop掉所有不优于新元素的元素. 然后在push_back新元素.
这货手敲就跟普通的queue一样方便, 用数组模拟即可.
能用单调队列来优化的问题, 必须具备一个性质, 就是在你新加入元素之后, 不优于这个新元素的元素都没有存在的必要了.
好了, 这题我们要求的是最大值, 用单调队列, 使index递增, 人品值递减. 为了方便, 我们可以再维护一个FIFO的普通队列, 模拟排队, 顺便来存每个人的人品值, 这样单调队列就可以只存人的序号了.
1/ 手敲版 (1078ms)
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<string>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
inline int Rint() { int x; scanf("%d", &x); return x; }
inline int max(int x, int y) { return (x>y)? x: y; }
inline int min(int x, int y) { return (x<y)? x: y; }
#define FOR(i, a, b) for(int i=(a); i<=(b); i++)
#define FORD(i,a,b) for(int i=(a);i>=(b);i--)
#define REP(x) for(int i=0; i<(x); i++)
typedef long long int64;
#define INF (1<<30)
const double eps = 1e-8;
#define bug(s) cout<<#s<<"="<<s<<" "
#define MAXN 1000002
int deq[MAXN]; //伪优先队列(deque双向队列)(序号递增, 值递减), 维护方法是尾端插入, 删除前面值小于它的元素.
int front, tail; //优先队列的指针
int q[MAXN]; //排队本身是 FIFO队列
int head, end; //FIFO队列的指针
int main()
{
int T = Rint();
while(T--)
{
front = tail = 0;
head = end = 0;
char buf[10];
scanf("%s", buf); //START
while(scanf("%s", buf) && buf[0]!='E')
{
char op = buf[0];
if(op=='C') //in
{
scanf("%s", buf); //NAME
int t = Rint();
q[end++] = t;
while(front<tail && q[deq[tail-1]]<t) tail--; //尾pop
deq[tail++] = end-1; //deq存的是序号
}
else if(op=='G') //out
{
head++;
}
else // Query
{
if(head<end)
{
while(deq[front]<head) front++; //首pop, deq不会为空
printf("%d\n", q[deq[front]]);
}
else
puts("-1");
}
}
}
}
2/ STL-deque版(1203ms)
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<string>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
using namespace std;
inline int Rint() { int x; scanf("%d", &x); return x; }
inline int max(int x, int y) { return (x>y)? x: y; }
inline int min(int x, int y) { return (x<y)? x: y; }
#define FOR(i, a, b) for(int i=(a); i<=(b); i++)
#define FORD(i,a,b) for(int i=(a);i>=(b);i--)
#define REP(x) for(int i=0; i<(x); i++)
typedef long long int64;
#define INF (1<<30)
const double eps = 1e-8;
#define bug(s) cout<<#s<<"="<<s<<" "
struct node { int v, id; };
deque<node> deq;
int front, tail;
int main()
{
int T = Rint();
while(T--)
{
while(!deq.empty()) deq.pop_back();
front = tail = 0;
char buf[10];
scanf("%s", buf); //START
while(scanf("%s", buf) && buf[0]!='E')
{
char op = buf[0];
if(op=='C') //in
{
scanf("%s", buf); //NAME
node t;
t.id = tail++;
t.v = Rint();
while(!deq.empty() && deq.back().v<t.v) deq.pop_back();
deq.push_back(t);
}
else if(op=='G') //out
{
front++;
}
else // Query
{
if(front<tail)
{
while(deq.front().id<front) deq.pop_front();
printf("%d\n", deq.front().v);
}
else
puts("-1");
}
}
}
}
3/ STL优先队列版....TLE
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<string>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
using namespace std;
inline int Rint() { int x; scanf("%d", &x); return x; }
inline int max(int x, int y) { return (x>y)? x: y; }
inline int min(int x, int y) { return (x<y)? x: y; }
#define FOR(i, a, b) for(int i=(a); i<=(b); i++)
#define FORD(i,a,b) for(int i=(a);i>=(b);i--)
#define REP(x) for(int i=0; i<(x); i++)
typedef long long int64;
#define INF (1<<30)
const double eps = 1e-8;
#define bug(s) cout<<#s<<"="<<s<<" "
#define MAXN 1000002
struct node
{
node(int i, int vv) { id=i; v=vv;}
int id, v;
};
bool operator<(node x, node y) // STL优先队列是按小于号决定优先级, 越大越优先
{
if(x.v!=y.v)
return x.v<y.v; //如果我希望大的先出来, 那只要把小于号重载为对应域的小于
else return x.id>y.id;
}
priority_queue<node> deq;
//queue<int> q;
int main()
{
int T= Rint();
while(T--)
{
getchar(); // '\0'
char buf[10];
gets(buf); //START
int idx = 0;
int front = 1, tail=1;
while(scanf("%s", buf) && buf[0]!='E')
{
char op = buf[0];
if(op == 'C') //in
{
scanf("%s", buf);
int w = Rint();
deq.push(node(++idx, w));
tail++;
}
else if(op=='G') //out
{
front++;
}
else // 'Q'
{
if(front<tail){}
else { puts("-1"); continue; }
for(node cur=deq.top(); cur.id<front; )
{
deq.pop();
cur = deq.top();
}
printf("%d\n", deq.top().v);
}
}
while(!deq.empty()) deq.pop();
}
}