思路:
士兵需要在怪物杀死自己前杀死怪物,便可以得到 d i / H j > D j / h i ⟹ d i ∗ h i > D j ∗ H j d_i / H_j > D_j / h_i \implies d_i * h_i > D_j * H_j di/Hj>Dj/hi⟹di∗hi>Dj∗Hj
由题可得,我们需要在有限的金币数量 ( C i ) (C_i) (Ci) 之内,使用最少的金币数量杀死怪物。假设需要 n n n 个 i i i 类士兵才能杀死怪物,便有公式 n ∗ d i ∗ h i > D j ∗ H j ⟹ n > d i ∗ h i D j ∗ H j n * d_i * h_i > D_j * H_j \implies n > \frac{d_i * h_i}{D_j * H_j} n∗di∗hi>Dj∗Hj⟹n>Dj∗Hjdi∗hi ,使用第 i i i 类士兵杀死怪物,我们需要花费的最少金币数量则为 c i ∗ ( d i ∗ h i D j ∗ H j + 1 ) c_i * \left(\frac{d_i * h_i}{D_j * H_j} + 1\right) ci∗(Dj∗Hjdi∗hi+1) ,最后对于每类士兵的最少花费的金币数量取 m i n min min 就是答案。
如何得到每类士兵杀死怪物的最少花费金币数量,这是第二个需要解决的问题。此时会发现很难在规定的时间内求出每类士兵杀死怪物的最少花费金币数量,遇见困难不妨转换一下思路,在固定金币数量的情况下我们所能购买到的最大战力 n ∗ d i ∗ h i n * d_i * h_i n∗di∗hi ,此时回到了公式 n ∗ d i ∗ h i > D j ∗ H j n * d_i * h_i > D_j * H_j n∗di∗hi>Dj∗Hj ,求大于 D j ∗ H J D_j * H_J Dj∗HJ 的最小 n ∗ d i ∗ h i n * d_i * h_i n∗di∗hi 方法最为直接的便是二分了。
总的时间复杂度为 O ( n + ( C + m ) l o g C ) O(n + (C + m)logC) O(n+(C+m)logC),计算金币数量 i i i 所能得到的最大战力的时间复杂度为 O ( C 1 + C 2 + ⋯ + C C ) = O ( C l o g C ) O(\frac{C}{1} + \frac{C}{2} + \cdots + \frac{C}{C}) = O(ClogC) O(1C+2C+⋯+CC)=O(ClogC)
int main(){
int n,C;
scanf("%d %d",&n,&C);
for(int i=1;i<=n;i++) {
int c;
ll d,h;
scanf("%d %lld %lld",&c,&d,&h);
maxn[c] = max(maxn[c],d*h);
}
for(int i=1;i<=C;i++) {
for(int j=1;j<=C/i;j++) {
maxn[j*i] = max(maxn[j*i],maxn[i] * j);
}
}
for(int i=1;i<=C;i++) maxn[i] = max(maxn[i],maxn[i-1]);
int p;
scanf("%d",&p);
while(p --) {
ll d,h;
scanf("%lld %lld",&d,&h);
if(d * h >= maxn[C]) printf("-1 ");
else printf("%d ",upper_bound(maxn+1,maxn+C+1,d * h) - maxn);
}
return 0;
}