Educational Codeforces Round 167 (Rated for Div. 2) D题题解记录

大致题意:有nnn种武器,每种武器可以花费同种锭aia_iai块铸造,融化返还bib_ibi块。现在有mmm种锭,分别有cic_ici块。而每次铸造和融化都会分别获得一点经验值。问最多能获得多少经验值。

不同种类的锭之间互相独立,我们可以分开计算。选择的武器一定是性价比最高的,即ai−bia_i-b_iaibi最小并且aia_iai也尽可能的小。这样满足消耗尽可能少并且门槛尽可能低。然后我们考虑,对于当前拥有xxx块同种类型的锭,我们要找到一个aia_iai满足ai<=xa_i<=xai<=x并且ai−bia_i-b_iaibi最小。那么我们考虑能不能针对所有锭数直接预处理出满足此条件的min(ai−bi)min(a_i-b_i)min(aibi)。如果xxx大于最大的aia_iai,我们一直可以选择性价比最高的,直到xxx不再大于最大的aia_iai。此时x<=aix<=a_ix<=ai,使用预处理的数据得到xxx下一步选谁。
fif_ifi表示当前有iii块锭的情况下,性价比最高的花费ai−bia_i-b_iaibi。那么首先可以推出来fai=min(ai−bi,fai)f_{a_i}=min(a_i-b_i,f_{a_i})fai=min(aibi,fai)。然后再对于i<=mai<=mai<=mafi=min(fi,fi−1)f_i=min(f_i,f_{i-1})fi=min(fi,fi1)
借助fff,我们可以进一步直接推出来当前有iii块锭的情况下,最多可以获得多少经验值。令gig_igi表示当前有iii块锭的情况下,最多可以获得多少经验值,那么gi=gi−fi+2g_i=g_{i-f_i}+2gi=gifi+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;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值