C. Circle of Monsters(思维)

Posted zjj0624

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C. Circle of Monsters(思维)相关的知识,希望对你有一定的参考价值。

题目链接
题意
有n个机器人围成一个圈,然后每个机器人有一个血量 a i a_i ai和一个死后的爆炸伤害 b i b_i bi,我们每次可以射击一个机器人,对其进行一点伤害,如果一个机器人被打死(血量小于等于0),这个机器人就会爆炸,爆炸会对自己后面一个机器人造成 b i b_i bi的伤害,可以产生连锁反应,问最后需要的最小的子弹数量,可以杀死所有的机器人。
思路
刚开始拿到这个题,我就想到了一个问题,就是不确定第一个开枪打谁。
如果我们确定了第一个打那个机器人,因为求的是最小的子弹数,所以每次肯定就是打这个后面的机器人,因为这样才可以充分到利用到爆炸伤害,如果我们第一个打第3个机器人,然后第二次打第二个机器人,那第二次的爆炸伤害就浪费了,所以这个问题的关键就是求第一个要打的机器人。
我们可以枚举开枪打的第一个机器人,剩下的可以用前缀和维护出剩下的花费,剩下的打每一个机器人的子弹肯定就是max(0, a i − b i − 1 a_i-b_{i-1} aibi1),我们可以用前缀和维护出来所有的和,然后就很好解决了。
代码

#include <bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pb push_back
#define me memset
const int N = 1e6;
const int MOD = 1e9+7;
const int INF = 0x3f3f3f3f;
using namespace std;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
PLL p[N];
ll ss[N];
ll c[N];
int n;
ll solve(int x)
{
    ll sum=p[x].fi;
    sum+=(ss[x+n-1]-ss[x]);
    return sum;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=1 ; i<=n ; i++) scanf("%lld%lld",&p[i].fi,&p[i].se);
        c[1]=max(p[1].fi-p[n].se,1ll*0);
        for(int i=2 ; i<=n ; i++) c[i]=max(1ll*0,p[i].fi-p[i-1].se);
        for(int i=1 ; i<=n ; i++) ss[i]=ss[i-1]+c[i];
        for(int i=n+1 ; i<=2*n-1 ; i++) ss[i]=ss[i-1]+c[i%n];
        ll ans=1e18;
        for(int i=1 ; i<=n ; i++)
        {
            ans=min(ans,solve(i));
        }
        printf("%lld\\n",ans);
    }
    return 0;
}

以上是关于C. Circle of Monsters(思维)的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces 1334C - Circle of Monsters(差值取前缀和 / 贪心)

C. Number of Ways 思维

F - The Circumference of the Circle

Circumference of circle

A. Circle of Students ( Codeforces Round #579 )

Code Signal_练习题_Circle of Numbers