Codeforces 976E 题解报告

一、题目

http://codeforces.com/contest/976/problem/E

二、分析

(1)当把所有的倍数2 ^ a都加到同一health上,health增加的最多
(2)先计算每一个creature的hp - dmg,按该值对所有的creature排序
再求和,i

三、程序

#include <bits/stdc++.h>
using namespace std;

const int N = 200 * 1000 + 9;
int hp[N], dmg[N];

// 按生命值和破坏值的差排序,差大的排在前
// 若差相等,按原先的顺序即从小到大
bool cmp(int i, int j)
{
    if(hp[i] - dmg[i] != hp[j] - dmg[j])
    {
        return hp[i] - dmg[i] > hp[j] - dmg[j];
    }
    return i < j;
}

// 得到生命值和破坏值中的较大者
int getMaxDesc(int id)
{
    return  hp[id] > dmg[id] ? hp[id] : dmg[id];
}

int main()
{
    int n, a, b;
    scanf("%d %d %d", &n, &a, &b);
    for(int i = 0; i < n; ++i)
    {
        scanf("%d %d", hp + i, dmg + i);
    }

    b = min(b, n);
    vector <int> creature(n);
    for(int i = 0; i < n; ++i)
    {
        creature[i] = i;
    }

    // 按creature的生命值和破坏值的差进行排序
    sort(creature.begin(), creature.end(), cmp);

    long long res = 0, sum = 0;
    for(int i = 0; i < n; ++i)
    {
        int id = creature[i];

        /*
         * 初始不考虑a
         * i<b,可以把生命值赋值给破坏值
         * i>=b,不能把生命值赋值给破坏值
         */
        if(i < b)
        {
            sum += getMaxDesc(id);
        }
        else
        {
            sum += dmg[id];
        }
    }
    res = sum;

    if(b == 0)
    {
        printf("%I64d\n", res);
        return 0;
    }

    // 所有的a加给同一creature时翻倍最多,倍数为2的a次幂
    long long mutiple = (1LL << a);
    for(int i = 0; i < n; ++i)
    {
        int id = creature[i];
        long long newsum = sum;

        if(i < b)
        {
            // 挨个用翻倍后的生命值来替换,看看哪个最大
            newsum -= getMaxDesc(id);
            newsum += hp[id] * mutiple;
            res = max(res, newsum);
        }
        else
        {
            // 因为排过序,在0~b-1步中,第b-1步获得的破坏值是最小的
            // 先让第b-1步不用生命值替换,直接取破坏值
            // 这样就获得了一次替换的机会
            int id2 = creature[b - 1];
            newsum -= getMaxDesc(id2);
            newsum += dmg[id2];

            // 利用上一步得来的替换机会,用翻倍后的生命值替换破坏值,看看哪个最大
            newsum -= dmg[id];
            newsum += hp[id] * mutiple;

            res = max(res, newsum);
        }
    }

    printf("%I64d\n", res);
    return 0;
}


TopCoder & Codeforces & AtCoder交流QQ群:648202993
更多内容请关注微信公众号
wechat_public_header.jpg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值