题目
题意:
我们总共有两种法术,一个闪电法术,一个火焰法术,闪电法术之后能够将下一个法术的伤害翻倍,现在你有两种操作学习/忘记,问你每一次操作后最大的伤害是多少。
思路:
我们可以设一个两个 s e t set set数组,一个用来存放一倍数字的,另一个存两倍数字的,对于每一次出现的数字,如果这个数字比一倍里面的全部都大的话,那么就有可能可以替换两倍数字里面的数字了,删除的话,我们需要根据这个数字大小,然后找到是在一倍还是二倍中,如果是在二倍中的,我们还需要知道这个是否是闪电,因为如果是火的话,那么我们还需要将再添加一个数字到二倍的中,最后还有一个问题,如果闪电是 k k k个,闪电最好的情况就是 k − 1 k-1 k−1个闪电+ 1 1 1个火,因为这个不是一个环,所以就有两种情况
- 有火,那么有一个双倍就是最大的火,然后比较这个火和之前两倍的最小,如果火比两倍的最小还要小的话,那么说明,闪电的均比火来的大,那么中间的差值就是 m i n u = 最 小 双 倍 − 最 大 火 minu=最小双倍-最大火 minu=最小双倍−最大火
- 无火,那么就说明全部都是闪电,那么直接 m i n u = 0 − 最 小 双 倍 minu=0-最小双倍 minu=0−最小双倍。
(ps:题解中的火,闪电,双倍均表示的是伤害)。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
#include <string>
#include <cmath>
#include <set>
#include <map>
#include <deque>
#include <stack>
#include <cctype>
using namespace std;
typedef long long ll;
typedef vector<int> veci;
typedef vector<ll> vecl;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
template <class T>
inline void read(T &ret) {
char c;
int sgn;
if (c = getchar(), c == EOF) return ;
while (c != '-' && (c < '0' || c > '9')) c = getchar();
sgn = (c == '-') ? -1:1;
ret = (c == '-') ? 0:(c - '0');
while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return ;
}
inline void outi(int x) {if (x > 9) outi(x / 10);putchar(x % 10 + '0');}
inline void outl(ll x) {if (x > 9) outl(x / 10);putchar(x % 10 + '0');}
int main() {
int n; read(n);
int cnt = 0;
ll ans = 0;
set<ll> file, set_one, set_two;
for (int i = 0; i < n; i++) {
ll tp, d; read(tp), read(d);
ans += d;
if (d > 0) {
if (tp == 1) cnt++;
else file.insert(d);
if (set_one.size() && d <= *set_one.rbegin()) set_one.insert(d);
else set_two.insert(d), ans += d;
} else {
if (tp == 1) cnt--;
else file.erase(-d);
if (set_one.size() && -d <= *set_one.rbegin()) set_one.erase(-d);
else set_two.erase(-d), ans += d;
}
while (set_two.size() > cnt) {
int x = *set_two.begin();
set_two.erase(x);
set_one.insert(x);
ans -= x;
}
while (set_two.size() < cnt) {
int x = *set_one.rbegin();
set_two.insert(x);
set_one.erase(x);
ans += x;
}
ll x = 0;
if (set_two.size()) {
if (file.size()) x = min(x, *file.rbegin() - *set_two.begin());
else x = 0 - *set_two.begin();
}
printf("%lld\n", ans + x);
}
return 0;
}