PPMM【JZOJ】

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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值