But my words, like si|

MessageBoxA

园龄:4年10个月粉丝:4关注:0

NOI模拟 大战波特

涉及知识点:贪心

前言

思维难度不高,就是挺好玩的,随手记录下有意思的贪心,奇妙的贪心经常比复杂的 DP 还有意思。

题意

打 Boss,总共可以打 n (106) 回合,每回合可以普攻一次,造成 x 点伤害,每回合可以使用咒语,总共最多使用 k 次,使得 Boss 赋予一层“中毒”效果,并减弱一层“回复”效果(如果之前存在“回复”效果的话),Boss 每回合也可以使用咒语给自己赋予一层”回复“效果,注意同一回合可以同时普攻与使用咒语。“中毒”效果指每回合结束后 Boss 受到 p 点伤害,“回复”效果指每回合结束后 Boss 得到 r 点血量。不存在血量上限或下限,效果可叠加,已知 Boss 哪些回合使用 ”回复“ 咒语,求 n 回合后 Boss 最多掉了多少血(可能为负数)。

思路

阻碍我们贪心的最大问题在于要同时考虑减弱”回复“效果和造成持续伤害,因此我们可以尝试将”回复“效果直接量化为血量的变化。并且有贪心策略:如果我们想要减弱某一层”回复“效果,一定是直接就在该”回复“效果产生的回合使用咒语最优,”回复“效果产生后几回合才减弱它是一定不优的。

我们首先假设每回合 Boss 的”回复“都生效且没被减弱,如果回合 i 时 Boss 使用了咒语,那么我方使用咒语带来的总伤害为 (p+r)(ni+1)(要把”回复“那部分抵消),否则总伤害为 p(ni+1),将每个回合使用咒语的预期伤害排序后选最大 k 个即可。并且使用或不使用咒语的伤害序列分别有单调性,最后可以使用归并排序做到严格线性。

FAQ:

有人可能会疑问为什么 Boss 不使用咒语时,我方使用咒语的伤害就只有 p(ni+1)?因为可以证明贪心到这个时候时 Boss 一定是没有”回复“效果的:如果 i 前面有某个回合 j Boss 使用了咒语并且没有被减弱,那么我们直接在 j 使用咒语造成的伤害一定更高。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN=1e6+5;
LL n,x,r,p,k;
LL ans=0,atk[MAXN];
string opt;
int main(){
    // freopen("bot.in","r",stdin);
    // freopen("bot.out","w",stdout);
    cin>>n>>x>>r>>p>>k>>opt;
    for(int i=0;i<n;i++){
        ans+=x;
        if(opt[i]=='1'){
            ans-=r*(n-i);
            atk[i]=(p+r)*(n-i);
        }
        else{
            atk[i]=p*(n-i);
        }
    }
    sort(atk,atk+n,greater<LL>());
    for(int i=0;i<k;i++){
        ans+=atk[i];
    }
    cout<<ans<<endl;
    return 0;
}

本文作者:MessageBoxA

本文链接:https://www.cnblogs.com/SkyNet-PKN/p/18183290

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   MessageBoxA  阅读(7)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 evening Corn Wave
  2. 2 Группа крови Кино
  3. 3 The Sound Of Silence Simon & Garfunkel
  4. 4 dB doll YUE.STEVEN
Группа крови - Кино
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.