CF976E Well played! 题解
解题思路
两个显然的结论:
- 将所有生物
的值按照从大到小的顺序排序后,将正值部分全部进行 操作(如果可以的话),这样是最优的; - 将所有的
操作全部在同一生物上进行是最优的,证明如下(假设只有两个,多个同样成立):- 令
,则 ,由此可得分开的值 ,在一个生物上进行的值为 ,不妨设 ; - 假设
,则 ,移项可得 ,带入得到 ,不等式两边同时除以 可得 ,又因为 ,故等式不成立, ; - 综上,将
全部赋为一个生物最优。
- 令
接下来只需要简单的贪心就可以了,但是有些细节需要注意一下。
AC 代码
#include<math.h>
#include<time.h>
#include<stdio.h>
#include<algorithm>
#define ll long long
#define N 200005
#define int ll
int n,a,b,d[N];
struct QWQ{int hp;int dmg;}s[N];
inline bool cmp(QWQ A,QWQ B){
if(A.hp-A.dmg==B.hp-B.dmg)
return A.hp>B.hp;
return A.hp-A.dmg>B.hp-B.dmg;
}
signed main(){
scanf("%lld%lld%lld",&n,&a,&b);
for(register int i=1;i<=n;++i){
scanf("%lld",&s[i].hp),
scanf("%lld",&s[i].dmg);
}std::sort(s+1,s+n+1,cmp);
int replace=0,maxt1=-1,res=0;
for(register int i=1;i<=n;++i)
res+=s[i].dmg,d[i]=s[i].dmg;
if(b==0){printf("%lld",res);return 0;}
if(b){for(register int i=1;i<=n;++i){
int sub=s[i].dmg;
int now=(1ll<<a)*s[i].hp-sub;
maxt1=std::max(maxt1,now);
}res=res+maxt1;
}for(register int i=1;i<=n;++i){
if(s[i].hp<=s[i].dmg||!b) break;
s[i].dmg=s[i].hp;--b;++replace;
}int ans=0;
for(register int i=1;i<=n;++i)
ans+=s[i].dmg;
int Maxt=-1,Mint=s[replace].dmg,Mini=replace;
for(register int i=1;i<=replace;++i){
if(s[i].hp>Maxt) Maxt=s[i].hp;
}int maxt=((1ll<<a)-1)*Maxt;
if(b>0){for(register int i=replace+1;i<=n;++i){
int sub=s[i].dmg;
int now=(1ll<<a)*s[i].hp-sub;
maxt=std::max(maxt,now);
}
}else{for(register int i=replace+1;i<=n;++i){
int sub=s[i].dmg;
int now=(1ll<<a)*s[i].hp-sub;
maxt=std::max(maxt,now-Mint+d[Mini]);
}
}printf("%lld",maxt+ans>res?maxt+ans:res);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下