# 题意
n个怪兽,每个怪兽有hp血量和atk攻击值,每一秒英雄都会受到所有存活怪兽的攻击,英雄攻击每个怪兽的伤害等于攻击当前怪兽的次数,第一次攻击第i个怪兽的伤害为1,第二次为2,计算英雄杀光所有怪兽后承受的最小攻击
数据范围:
T:1e3
n:(1,1e5)
所有测试数据的n的和<1e6
Hp,atk [ 1 , 1e5 ]
# 题解
总体思想:先搞死伤害高的
n个怪兽每个怪兽最大都是1e5,总和会爆int,使用long long
将每个怪兽的存活时间计算出,计算出它的平均伤害
按照平均伤害为第一关键字,攻击值为第二关键字从大到小排序
比值排序有精度误差 ,可以改成这样: a/b > c/d= a*d > b*c
1 #pragma GCC optimize(3,"Ofast","inline") 2 #include <bits/stdc++.h> 3 #define LL long long 4 using namespace std; 5 const int N=1e5+10; 6 struct monster{ 7 LL hp; 8 LL atk; 9 LL alive;//预处理所有怪兽从被攻击开始能够存活的时间 10 double average;//存活时间内的平均攻击 11 }mon[N]; 12 inline LL Alive(LL x){ 13 LL tim,res=0; 14 for (int i = 1;; ++i){ 15 res+=i; 16 if(res>=x){ 17 tim=i; 18 break; 19 } 20 } 21 return tim; 22 } 23 inline bool cmp(struct monster A,struct monster B){ 24 if(A.average==B.average) 25 return A.atk>B.atk; 26 return A.average>B.average; 27 } 28 int main(){ 29 ios::sync_with_stdio(0); 30 cin.tie(0); 31 cout.tie(0); 32 int T; 33 cin>>T; 34 LL sum_atk; 35 for (int i = 1; i <=T ; ++i) { 36 int n; 37 cin>>n; 38 sum_atk =0; 39 for (int i = 1; i <=n ; ++i) { 40 cin>>mon[i].hp>>mon[i].atk; 41 mon[i].alive= Alive(mon[i].hp); 42 mon[i].average = mon[i].atk*1.0/mon[i].alive; 43 sum_atk+=mon[i].atk; 44 } 45 LL hurt=0; 46 sort(mon+1,mon+n+1,cmp); 47 for (int i = 1; i <=n ; ++i) { 48 hurt+=sum_atk*mon[i].alive; 49 sum_atk-=mon[i].atk; 50 } 51 cout<<"Case #"<<i<<": "<<hurt<<endl; 52 } 53 return 0; 54 }