C题直接贪心,D题欧拉回路,理论上应该会做的……
然后应该读题比较慢的关系,A题+B题各做了20分钟……还是15分钟内连切两道比较理想,毕竟挂了梯子,开CF的速度也不慢。
C. Circle of Monsters
\(n\)只怪物站成一圈,第\(i\)只怪物有\(a[i]\)点生命值和\(b[i]\)点爆炸伤害。当第\(i\)只怪物死亡时会爆炸,且只对第\(i+1\)只怪物造成\(b[i]\)点伤害。爆炸可以传递。每次开枪会对其中一只怪物造成\(1\)点伤害,求能杀死全部怪物的最小开枪次数。
这题的数据范围有点emmm,我还以为要想办法写\(O(1)\)来着,其实是\(O(n)\)。
对每只怪物视为首个击杀目标,计算要补枪的次数(就是其它怪物扣除爆炸伤害后的剩余血量)遍历n只就好,用set维护最小值(感觉get到了什么新用法……)。
注意\(n==1\)时特判一下。
#include<iostream>
#include<map>
#include<cstring>
#include<math.h>
#include<algorithm>
#include<set>
using namespace std;
const int N = 1e5 + 5;
int main()
{
int q;
cin >> q;
while (q--) {
int n;
cin >> n;
long long int arr[N], pow[N], shrey[N];
set<long long int> s;
cin >> arr[0] >> pow[0];
if (n == 1) {//只有一只怪物,特判
cout << arr[0] << endl;
continue;
}
long long int sum = 0;//不会被直接炸死的怪物的剩余血量
for (int i = 1;i < n;i++) {
cin >> arr[i] >> pow[i];
shrey[i] = arr[i] - pow[i - 1];//shrey[i]是第i只怪物被炸后的剩余血量
if (shrey[i] > 0) {//不会被直接炸死
sum += shrey[i];//剩余血量
}
}
shrey[0] = arr[0] - pow[n - 1];
if (shrey[0] > 0) sum += shrey[0];
for (int i = 0;i < n;i++) {
if (shrey[i] > 0) {
s.insert(sum - shrey[i] + arr[i]);
//总残余血量-这只怪物残余血量+这只怪物生命值
//即将它视为首个目标时需要的子弹数量
}
else {
s.insert(sum + arr[i]);//总残余血量-(0)+生命值
}
}
cout << *s.begin() << endl;//输出最小值
}
return 0;
}
原文地址:https://www.cnblogs.com/streamazure/p/12677497.html
时间: 2024-10-09 09:05:51