Educational Codeforces Round 125 (Rated for Div. 2) D(二分)

D. For Gamers. By Gamers.

题意

题目好难懂
每场战斗之前有C枚金币,可以从n个队伍中选一个,该支队伍可以选任意个
每个队伍都有一些属性:ci花费,di伤害,hi生命值
有m个怪物,每个怪物有属性:Di伤害 Hi生命值
要求的是能打败怪物的最小花费

思路

提取出信息:要打败怪物必须满足di*hi*cnt > Dj*Hj
二分花费1~C
f[i]记录花费为i时,最大的di*hi*cnt

代码

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;
typedef long long LL;

const int N = 1000010;
vector<LL> G[N];    //记录花费为i时的战力
LL f[N];    // 花费为i的最大战力

int main()
{
    int n, C;
    cin >> n >> C;
    LL c, d, h;
    for(int i = 0; i < n; i ++ )
    {
        scanf("%lld%lld%lld", &c, &d, &h);
        G[c].push_back(d*h);
    }
    
    for(int i = 1; i <= C; i ++ )
    {
        if(G[i].size() == 0)    continue;
        int cnt = G[i].size();
        sort(G[i].begin(), G[i].end());
        for(int j = 1; j * i <= C; j ++ )   // 枚举能选多少队伍
        {
            f[i * j] = max(f[i * j], j * G[i][cnt - 1]);
        }
    }
    // 由于f[i]不一定递增,f[i]需要取1~i中最大的
    for(int i = 2; i <= C; i ++ )
        f[i] = max(f[i], f[i - 1]);

    int m;
    cin >> m;
    while (m -- )
    {
        LL d, h;
        scanf("%lld%lld", &d, &h);
        // 二分
        LL l = 1, r = C;
        while(l < r)
        {
            LL mid = l + r >> 1;
            if(f[mid] > d * h)  r = mid;
            else    l = mid + 1;
        }
        if(f[l] <= d * h)   printf("%d ", -1);
        else    printf("%lld ", l);
    }
    
    return 0;
}
posted @ 2022-03-25 16:25  inss!w!  阅读(21)  评论(0编辑  收藏  举报