前言
今天3道题都卡常。。。都吸了氧才过。。。
题目
题目链接:
请实现一个队列,支持如下四种操作。
PUSH X:将整数X加入到队尾。
POP:将队首的数字出队。
MINUS:队列中所有数字都变为其相反数,即X←-X。
MAX:返回队列中最大的数。
对于操作POP、MINUS和MAX,如果队列为空,则直接忽略它们。
现在给定一个操作序列,对于其中的每个MAX操作,如果它没有被忽略,请输出它所返回的数。
思路
对于\(\rm PUSH,POP,MAX\)操作都是堆的基础操作。维护一个大根堆和一个删除堆即可。
容易发现,\(\rm MINUS\)操作将队列的数字变为其相反数,相当于将后面才加入队列的数取相反数,然后\(\rm MAX\)操作时取最小值的相反数。
那么在维护一个小根堆和一个小根删除堆即可。
时间复杂度\(O(n\log n)\)。
代码
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#include <queue>
#include <cctype>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=2000010;
int n,head,tail,a[N];
bool flag;
char ch[10];
priority_queue<int> qs,qb,delb,dels;
int read()
{
int d=0,f=1; char ch=getchar();
while (!isdigit(ch)) f=ch=='-'?-1:f,ch=getchar();
while (isdigit(ch)) d=(d<<3)+(d<<1)+ch-48,ch=getchar();
return d*f;
}
int main()
{
n=read();
head=1;
while (n--)
{
scanf("%s",ch);
if (ch[1]=='U')
{
a[++tail]=read();
if (flag) a[tail]=-a[tail];
qb.push(a[tail]); qs.push(-a[tail]);
}
if (ch[1]=='O')
if (head<=tail)
{
delb.push(a[head]);
dels.push(-a[head]);
head++;
}
if (ch[1]=='I') flag^=1;
if (ch[1]=='A')
{
if (head>tail) continue;
if (!flag)
{
while (qb.size() && delb.size() && qb.top()==delb.top())
qb.pop(),delb.pop();
printf("%d\n",qb.top());
}
else
{
while (qs.size() && dels.size() && qs.top()==dels.top())
qs.pop(),dels.pop();
printf("%d\n",qs.top());
}
}
}
return 0;
}