写这篇题解前重复一句被很多人说过的话...."一直以为单调队列就是优先队列, 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(); } }