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;
}