codeforces E. Two Types of Spells

在这里插入图片描述

题目

题意:

我们总共有两种法术,一个闪电法术,一个火焰法术,闪电法术之后能够将下一个法术的伤害翻倍,现在你有两种操作学习/忘记,问你每一次操作后最大的伤害是多少。

思路:

我们可以设一个两个 s e t set set数组,一个用来存放一倍数字的,另一个存两倍数字的,对于每一次出现的数字,如果这个数字比一倍里面的全部都大的话,那么就有可能可以替换两倍数字里面的数字了,删除的话,我们需要根据这个数字大小,然后找到是在一倍还是二倍中,如果是在二倍中的,我们还需要知道这个是否是闪电,因为如果是火的话,那么我们还需要将再添加一个数字到二倍的中,最后还有一个问题,如果闪电是 k k k个,闪电最好的情况就是 k − 1 k-1 k1个闪电+ 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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值