大致题意:有nnn种武器,每种武器可以花费同种锭aia_iai块铸造,融化返还bib_ibi块。现在有mmm种锭,分别有cic_ici块。而每次铸造和融化都会分别获得一点经验值。问最多能获得多少经验值。
解
不同种类的锭之间互相独立,我们可以分开计算。选择的武器一定是性价比最高的,即ai−bia_i-b_iai−bi最小并且aia_iai也尽可能的小。这样满足消耗尽可能少并且门槛尽可能低。然后我们考虑,对于当前拥有xxx块同种类型的锭,我们要找到一个aia_iai满足ai<=xa_i<=xai<=x并且ai−bia_i-b_iai−bi最小。那么我们考虑能不能针对所有锭数直接预处理出满足此条件的min(ai−bi)min(a_i-b_i)min(ai−bi)。如果xxx大于最大的aia_iai,我们一直可以选择性价比最高的,直到xxx不再大于最大的aia_iai。此时x<=aix<=a_ix<=ai,使用预处理的数据得到xxx下一步选谁。
令fif_ifi表示当前有iii块锭的情况下,性价比最高的花费ai−bia_i-b_iai−bi。那么首先可以推出来fai=min(ai−bi,fai)f_{a_i}=min(a_i-b_i,f_{a_i})fai=min(ai−bi,fai)。然后再对于i<=mai<=mai<=ma,fi=min(fi,fi−1)f_i=min(f_i,f_{i-1})fi=min(fi,fi−1)。
借助fff,我们可以进一步直接推出来当前有iii块锭的情况下,最多可以获得多少经验值。令gig_igi表示当前有iii块锭的情况下,最多可以获得多少经验值,那么gi=gi−fi+2g_i=g_{i-f_i}+2gi=gi−fi+2。
code
void solve() {
int n, m;
cin >> n >> m;
int ma = 0;
vector<int> a(n + 1), b(n + 1);
for (int i = 1; i <= n; i++) {
cin >> a[i];
ma = max(ma, a[i]);
}
vector<int> f(max(ma, n) + 10, inf);
for (int i = 1; i <= n; i++) {
cin >> b[i];
f[a[i]] = min(f[a[i]], a[i] - b[i]);
}
vector<int> g(ma + 1);
for (int i = 1; i <= ma; i++) {
f[i] = min(f[i], f[i - 1]);
if (f[i] == inf) continue;
g[i] = g[i - f[i]] + 2;
}
int ans = 0;
while (m--) {
int x;
cin >> x;
if (x <= ma) ans += g[x];
else {
int c = (x - ma) / f[ma] + 1;
ans += c * 2 + g[x - c * f[ma]];
}
}
cout << ans << endl;
}