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}
ai−bi−1),我们可以用前缀和维护出来所有的和,然后就很好解决了。
代码
#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(差值取前缀和 / 贪心)
F - The Circumference of the Circle