Official

D - Get Many Stickers Editorial by en_translator


Let \(D_i = A_i - B_i\). In fact, the following greedy algorithm is optimal: perform exchanges as many times as possible in ascending order of \(D_i\). More specifically, the following algorithm is valid:

  • Let \(\mathrm{ans}=0\).
  • While there exists \(i\) with \(N\geq A_i\), repeat the following:
    • Take \(i\) with the minimum \(D_i\) among those with \(N\geq A_i\). (Take any of them if there are multiple such indices.) Set \(N\leftarrow N-A_i+B_i\) (or subtract \(D_i\) from \(N\)), and add \(1\) to \(\mathrm{ans]\).

However, in this problem \(N\) can be up to \(10^{18}\), so this algorithm cannot be directly applied. Instead, we modify the algorithm as follows.

  • Let \(\mathrm{ans}=0\).
  • Rearrange \(A\) and \(B\) to make \(D_1 \leq D_2\leq \dots \leq D_M\).
  • For \(i=1,2,\dots,M\) in order:
    • Let \(x\) be the maximum number of operations applied for this \(i\). Namely, let \(x=\max\left\{0, \left\lfloor\frac{N-A_i}{D_i}\right\rfloor+1\right\}\). Subtract \(D_i\times x\) from \(N\), and add \(x\) to \(\mathrm{ans}\).

The computational complexity is \(O(M\log M)\), where the initial sorting is bottleneck.

Sample code (C++):

#include <bits/stdc++.h>

using namespace std;

using ll = long long;

int main() {
    ll n;
    int m;
    cin >> n >> m;
    vector<tuple<ll, ll, ll>> ls;
    for (int i = 0; i < m; i++) {
        ll a, b;
        cin >> a >> b;
        ll d = a - b;
        ls.emplace_back(d, a, b);
    }
    sort(ls.begin(), ls.end());
    ll ans = 0;
    for (auto [d, a, b]: ls) {
        if (a > n) continue;
        ll x = (n - a) / d + 1;
        ans += x;
        n -= x * d;
    }
    cout << ans << endl;
}

posted:
last update: