CF1266E 孤独的太空船

1 CF1266E 孤独的太空船

2 题目描述

时间限制 \(1s\) | 空间限制 \(256M\)

\(Bob\) 在玩一个孤独的太空船的游戏。游戏的目标是建立一艘太空船。他必须先要积累足够的建筑资源才能去建立太空船。总共有 \(n\) 种编号从 \(1\)\(n\) 的资源。第 \(i\) 种资源最起码需要 \(a_i\) 个才行,数字 \(a_i\) 被称为资源 \(i\) 的目标值。每种资源需要 \(1\) 个步骤来生产,每个步骤只能产生一种资源。每个奖励是一个三个数字 \((s_j,t_j,u_j)\) 表示,代表 \(Bob\)\(t_j\) 个资源 \(s_j\),他收到免费的一个单元的 \(u_j\),也就是说不需要花费步骤来生产。有可能获得免费资源使得 \(Bob\) 能够申请其他的奖励。这样他一次就可以获得大量的资源。这个游戏固定从来不会有两个奖励有相同的 \(s_j\)\(t_j\)。也就是说,达到 \(t_j\) 个资源 \(s_j\) 的奖励最多一个附加资源。任何 \(0\) 资源都不会得到奖励,不管是达到或者超越目标,也就是说 \(0 < t_j < a_{sj}\)。达到一定数量的资源的奖励可以是资源本身,即 \(𝑠_𝑗=𝑢_𝑗\)。最开始的时候是没有奖励的,你要处理 \(q\) 次更新,每次都增减,减少或者修改一个奖励。在每次更新后输出完成游戏需要的最少轮数,也就是说,对所有的资源 \(i\) \((i \in [1,n])\) 都最少积累 \(a_i\)个。

数据范围:\(1≤ 𝑛 ≤ 2\times 10^5\), \(1 ≤ 𝑎_𝑖 ≤ 10^9\), \(1 ≤ 𝑞 ≤ 10^5\).

3 题解

我们发现,由于 \(1 \le t_j < a_{s_j}\),所以该奖励一定会被触发,我们当前奖励就可以看成将 \(u_j\) 的当前值直接 \(+1\)。为了查看是否存在重复的 \(s_j\)\(t_j\),我们可以用 \(map\) 存储每一个奖励的 \(s_j\)\(t_j\),而当前 \(map\) 值表示的就是对于二元组 \((s_j, t_j)\),最新的 \(u_j\)。我们用 \(ans\) 记录最小回合数,最开始,这个值就是 \(\sum_{i = 1}^{n} \limits a_i\)

如果我们在输入 \(s_j, t_j, u_j\) 时发现存在 \((s_j, t_j)\) 这一二元组,那么我们就用新的 \(u_j\) 覆盖这二元组之前对应的 \(u_j\)。此时,我们将之前的 \(u_j\) 那一位的 \(a\) 值增加,意思就是达成满级需要多花费一个回合,把之前的操作撤销。加完之后,如果 \(u_j\) 对应的 \(a\) 值小于等于 \(0\),那么我们并不需要花费回合将这个资源增加:其他的奖励已经可以满足当前这一资源的要求。但是如果这一项的 \(a\) 值大于 \(0\),那么我们刚才往 \(a\) 中增加的那个 \(1\) 就对 \(ans\) 起了作用,答案就需要增加 \(1\),为了撤销之前减少的那个 \(1\)

处理完重复的情况,我们再来看看我们新找到的 \(u_j\)。很显然,我们需要把新的 \(u_j\) 对应的 \(a\) 值减少 \(1\)。此时,如果这个数本来就已经在奖励下达到了目标,那么我们新减少的这个 \(1\) 就不会对答案造成影响,否则答案就要减少 \(1\)

4 代码(空格警告):

#include <iostream>
#include <map>
#include <cstdio>
using namespace std;
typedef long long ll;
const int N = 2e5+10;
ll n, q, s, t, u;
ll a[N];
ll ans;
map< pair<ll, ll>, ll> M;
pair<ll, ll> add;
int main()
{
    scanf("%lld", &n);
    for (int i = 1; i <= n; i++) scanf("%lld", &a[i]), ans += a[i];
    scanf("%lld", &q);
    for (int i = 1; i <= q; i++)
    {
        scanf("%lld %lld %lld", &s, &t, &u);
        add = make_pair(s, t);
        if (M[add])
        {
            a[M[add]]++;
            if (a[M[add]] > 0) ans++;
        }
        M[add] = u;
        if (a[u] > 0) ans--;
        a[u]--;
        printf("%lld\n", ans);
    }
    return 0;
}

欢迎关注我的公众号:智子笔记

posted @ 2021-03-05 23:06  David24  阅读(71)  评论(0编辑  收藏  举报