實現一個隊列,完成以下四個操作
PUSH X:將整數X加入到隊尾。
POP:將隊首的數字出隊。
MINUS:隊列中所有數字都變爲其相反數,即X —> -X。
MAX:返回隊列中最大的數。
如果隊列爲空,POP,MINUS,MAX操作可忽略
輸入第一行爲正整數N,表示操作的個數。
接下來N行,每行爲一個操作。所有操作都用大寫字母表示。PUSH操作後會接着一個正整數X。
對於每個沒有被忽略的MAX操作,輸出其返回的數字,每個數字各佔一行。
6
PUSH -2
MINUS
PUSH -1
MAX
POP
MAX
2
-1
-2^31 < X < 2^31
對於20%的數據有 N ≤ 100
對於50%的數據有N ≤ 10,000
對於100%的數據有N ≤ 2,000,000
先來兩個堆
分別記錄隊列裏的數與其相反數
然後當有數需出隊時
再來兩個堆
將其數加進這兩個堆中
(其中一個裝相反數)
然後當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;
}