#C240130B. 刷野I
标签(Label)
- 思维
前言(Front talk)
$\qquad$非常好题目,使我时间花费。
网址(Website)
$\qquad$ 题目详情 - 刷野I - Super
$\qquad$ 题解 - 刷野I - Super
题解(Solution)
$\qquad$ 很明显,先将怪物的血量排序,从小打到大最后一定是最优的。整体的思路是从结果推来的,我们先用最朴素的普通攻击计算伤害,然后再计算操作1和操作2对答案的贡献即可。
$\qquad$ 对于操作一,总共要花费的血量为:$\sum_{i=1}^{n}(n-i+1)*a[i]$
$\qquad$ 对于操作二,每次肯定不会用操作二来打只有一滴血的怪,所以至少要打两滴血及以上的,相较于普通攻击来说会让当前幸存的怪物少打一轮,贡献为:$(n-i+1)$
$\qquad$ 对于操作三,贡献为让每一个幸存的怪物都少打一次,第 $i$ 个怪物掉一滴血贡献为 $(n-i+1)$ ,第 $i+1$ 个的贡献为 $n-(i+1)+1$ 。。。以此类推,可以得到等差数列,直接求和可得操作三的贡献为: $(n-l+i)*(n-l)/2$。
代码(Code)
#include<bits/stdc++.h>
#include<vector>
#include<queue>
#include<set>
#define For(i,l,r) for(int i=l;i<=r;i++)
#define Rof(i,l,r) for(int i=l;i>=r;i--)
using namespace std;
#define int long long
inline int input(){int x;return cin>>x,x;}
const int inf = 0x3f3f3f3f3f3f3f3f;
const int N = 101234;
int n,m,ans,a[N];
void Solve(){
For(i,1,n) ans+=(n-i+1)*a[i];
ans-=n;//打死怪物不需要扣血
int l=1,d=0;//d:放的三技能个数
while(m && l<=n){
if(a[l]-d<=0){l++;continue;}
if(a[l]-d==1){
if(n-l>=1){//如果不是最后一个
ans-=(n-l+1)*(n-l)/2;
d++;
m--;
}else l++;//最后一个1血怪直接普攻打死
}else{
int res1=0,res2=0;
if(n-l>=2){//如果至少有三个怪物,用3技能才更优
ans-=(n-l+1)*(n-l)/2;
d++;
m--;
}else{
ans-=n-l+1;
a[l]-=2;
m--;
}
}
}return cout<<ans<<'\n',void();
}
signed main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
string str("jungle");
freopen((str+".in").c_str(),"r",stdin);
freopen((str+".out").c_str(),"w",stdout);
cin>>n>>m;For(i,1,n) a[i]=input();
int Tim=clock();
sort(a+1,a+n+1);Solve();
return cerr<<"TIME:"<<(clock()-Tim)/1000.,0;
}