D e s c r i p t i o n Description Description
实现一个队列,完成以下四个操作
PUSH X:将整数X加入到队尾。
POP:将队首的数字出队。
MINUS:队列中所有数字都变为其相反数,即X —> -X。
MAX:返回队列中最大的数。
如果队列为空,POP,MINUS,MAX操作可忽略
I n p u t Input Input
输入第一行为正整数N,表示操作的个数。
接下来N行,每行为一个操作。所有操作都用大写字母表示。PUSH操作后会接着一个正整数X。
O u t p u t Output Output
对于每个没有被忽略的MAX操作,输出其返回的数字,每个数字各占一行。
S a m p l e Sample Sample I n p u t Input Input
6
PUSH -2
MINUS
PUSH -1
MAX
POP
MAX
S a m p l e Sample Sample O u t p u t Output Output
2
-1
H i n t Hint Hint
-2^31 < X < 2^31
对于20%的数据有 N ≤ 100
对于50%的数据有N ≤ 10,000
对于100%的数据有N ≤ 2,000,000
T r a i n Train Train o f of of T h o u g h t Thought Thought
先来两个堆
分别记录队列里的数与其相反数
然后当有数需出队时
再来两个堆
将其数加进这两个堆中
(其中一个装相反数)
然后当MAX时
先一个while处理相对应的两个堆的堆顶是否相等
因为当相等时
就表示这个数早已出队
然后将这个数从堆中踢出
记得用一个数组当队列
否则无法确定出队的是哪一个数
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
priority_queue<int>A, A_, B, B_;
int T, k, l, r;
int F[2000250];
char s[10];
int flag;
int read()
{
int x = 0,flag = 1;char c = getchar();
while(c < '0' || c>'9'){if(c == '-')flag = -1;c = getchar();}
while(c >= '0' && c <= '9'){x = x * 10 + c - '0', c = getchar();}
return x * flag;
}
void write(int x)
{
if(x < 0){x = -x;putchar('-');}
if(x > 9)write(x / 10);
putchar(x % 10 + 48);
return;
}
int main()
{
T = read();
flag = 0, l = 1;
for(register int t = 1; t <= T; ++t)
{
scanf("%s", s);
if(s[1] == 'U')
{
F[++r] = read();
if(flag)F[r] = -F[r];
A.push(F[r]);
A_.push(-F[r]);
}
else if(s[1] == 'O' && l <= r)
{
B.push(F[l]);
B_.push(-F[l]);
l++;
}
else if(s[1] == 'I')flag = (flag + 1) % 2;
else if(s[1] == 'A' && l <= r)
{
if(!flag)
{
while(A.size() && B.size() && A.top() == B.top())
A.pop(), B.pop();
write(A.top());
putchar('\n');
}
else
{
while(A_.size() && B_.size() && A_.top() == B_.top())
A_.pop(), B_.pop();
write(A_.top());
putchar('\n');
}
}
}
return 0;
}