ICPC 2020
ICPC 2020

I. Quests

To relax before competing in the ICPC World Finals, you have decided to play a computer game called Quests. You have played it a number of times already, and now you want to achieve a perfect playthrough—to prepare for your perfect playthrough of the finals...

Updated May 21, 2026
Track ICPC
Year 2020
Statement Text + PDF
TeXC++Statement textStatement PDF

Problem Statement

Formatted from the contest statement text, with sample tests broken out into copyable blocks.

Time limit 10 seconds

To relax before competing in the ICPC World Finals, you have decided to play a computer game called Quests. You have played it a number of times already, and now you want to achieve a perfect playthrough—to prepare for your perfect playthrough of the finals! In the game, you have to complete a number of quests, and you earn experience points (XPs) for com- pleting each one. The total number of XPs you have earned at any time determines your current level. You reach a new level for every v XPs that you earn. Formally, your level at any time is the largest integer L such that you have at least L · v XPs. Each quest is assigned a number x of XPs and a target difficulty level d. If you complete the quest when your level is at least d, you earn x XPs. However, if you complete the quest when your level is less than d, you will earn c · x XPs. The constant c is an XP multiplier that results in a bonus for completing a quest when you are at a lower level than the recommended level d. You know all the n quests and their respective x and d numbers by heart (and you know the numbers v and c as well—you have played this game a lot). You are also skilled enough to complete any quest, regardless of its target difficulty level and your level. You want to complete all the quests in an order that will allow you to earn the largest possible number of XPs. For example in the sample input, the maximum XPs you can earn is 43, which is done as follows. First complete the second quest (you earn 4 XPs, because you are at level 0, and you completed a quest with target difficulty level 2). Then complete the first quest (you earn 30 XPs, because you are still at level 0, and the target difficulty level is 1). With 34 XPs, you are now level 3. Finally, complete the third quest (for which you earn 9 XPs, without the multiplier, since you are already at level 3).

Input

The first line of input contains three integers n, v, and c, where n (1 ≤ n ≤ 2 000) is the number of quests in the game, v (1 ≤ v ≤ 2 000) is the number of XPs required to reach each level, and c (2 ≤ c ≤ 2 000) is the XP multiplier for completing a quest before reaching its target difficulty level. Following that are n lines, each of which contains two integers x and d describing one quest, where x (1 ≤ x ≤ 2 000) is the number of XPs you earn for completing that quest if you are at or above its target difficulty level and d (1 ≤ di ≤ 106 ) is the target difficulty level for that quest.

Output

Output the maximum possible number of XPs you could earn by finishing all the quests.

Sample Tests

Sample 1
Sample Input
3 10 2
15 1
2 2
9 1
Sample Output
43

Editorial

The solution write-up is rendered from the LaTeX source, with equations kept live through MathJax.

Key Observations

  • If a quest receives the multiplier, all quests done before it also receive the multiplier. Therefore in an optimal order, all multiplied quests come first, and all non-multiplied quests come after them.

  • Let $Y$ be the sum of the base XP values of the multiplied quests already completed. Then the actual XP earned so far is exactly $cY$. So quest $i$ with parameters $(x_i,d_i)$ can still be multiplied exactly when \[ cY < d_i v. \]

  • This is equivalent to \[ Y \le \left\lfloor \frac{d_i v - 1}{c} \right\rfloor. \] So if we only look at multiplied quests, quest $i$ behaves like a job with:

    • processing time $x_i$,

    • value $x_i$,

    • latest allowed start time \[ A_i = \left\lfloor \frac{d_i v - 1}{c} \right\rfloor. \]

    • Turning a start-time bound into an ordinary completion deadline gives \[ D_i = A_i + x_i. \] Then a set of multiplied quests is feasible iff it can be scheduled so that every selected job finishes by its deadline $D_i$.

    • This is now a standard deadline knapsack: after sorting by deadline, if total selected processing becomes $s$, then quest $i$ may be the last selected quest exactly when \[ s \le D_i. \]

    Algorithm

    1. For every quest compute \[ D_i = \left\lfloor \frac{d_i v - 1}{c} \right\rfloor + x_i. \] Also compute the base total \[ B = \sum x_i. \]

    2. Sort the quests by increasing $D_i$.

    3. Let reachable[s] mean: after processing some prefix of the sorted quests, there exists a feasible set of multiplied quests whose total base-XP sum is exactly $s$. Initially only reachable[0] is true.

    4. Process quests in sorted order. For quest $i$, update the bitset as a $0/1$ knapsack transition: from every reachable sum $s-x_i$, we may reach $s$ if \[ s \le D_i. \]

    5. Let $S$ be the largest reachable sum after all quests. Then the final answer is \[ B + (c-1)S, \] because every multiplied quest contributes an extra $(c-1)x_i$ above its base reward.

    Correctness Proof

    We prove that the algorithm returns the correct answer.

    Lemma 1.

    There exists an optimal playthrough in which every multiplied quest is done before every non-multiplied quest.

    Proof.

    Every quest always contributes its base reward $x$. Doing a non-multiplied quest earlier can only increase the current XP and level, which can never help a later quest receive the multiplier. So if a non-multiplied quest appears before a multiplied one, swapping them cannot decrease the reward of either quest. By repeatedly applying this swap, we obtain an optimal order with all multiplied quests first. □

    Lemma 2.

    If quest $i$ is multiplied after previously multiplied quests with total base-XP sum $Y$, then this is possible exactly when \[ Y \le \left\lfloor \frac{d_i v - 1}{c} \right\rfloor. \]

    Proof.

    By Lemma 1, only multiplied quests matter before quest $i$. If their base-XP sum is $Y$, the actual XP already earned is $cY$. Quest $i$ is multiplied exactly when the current level is less than $d_i$, i.e. \[ cY < d_i v. \] Since all quantities are integers, this is equivalent to \[ Y \le \left\lfloor \frac{d_i v - 1}{c} \right\rfloor. \] □

    Lemma 3.

    A set of multiplied quests is feasible iff, after giving each quest deadline \[ D_i = \left\lfloor \frac{d_i v - 1}{c} \right\rfloor + x_i, \] it can be scheduled so that every selected quest finishes by its deadline.

    Proof.

    For a selected quest $i$, let $Y$ be the total base-XP sum of earlier selected quests. By Lemma 2, quest $i$ is feasible exactly when $Y \le A_i$, where \[ A_i = \left\lfloor \frac{d_i v - 1}{c} \right\rfloor. \] Since quest $i$ itself contributes $x_i$, this is equivalent to \[ Y + x_i \le A_i + x_i = D_i. \] But $Y+x_i$ is exactly the completion time of quest $i$ in the scaled scheduling model. □

    Lemma 4.

    After sorting quests by nondecreasing deadlines, the bitset DP computes exactly all feasible total base-XP sums of multiplied quests.

    Proof.

    For ordinary single-machine scheduling with deadlines, every feasible subset is feasible in nondecreasing-deadline order. So when processing quests in that order, a total sum $s$ is feasible exactly when there exists a feasible sum $s-x_i$ from earlier quests and \[ s \le D_i. \] This is exactly the transition implemented by the DP. Therefore the final bitset contains precisely all feasible multiplied-base-XP totals. □

    Theorem.

    The algorithm outputs the correct answer for every valid input.

    Proof.

    By Lemma 1, we may restrict attention to a prefix of multiplied quests. By Lemma 3, choosing that prefix is equivalent to choosing a feasible subset in the deadline model. By Lemma 4, the DP finds the maximum possible total base-XP sum $S$ of such a subset. Each quest always contributes its base reward, and each multiplied quest contributes an additional $(c-1)x$. Hence the maximum final XP is exactly \[ \sum x_i + (c-1)S, \] which is what the algorithm outputs. □

    Complexity Analysis

    Let \[ X = \sum x_i \le 4\,000\,000. \] The bitset has $X+1$ states. Each of the $n$ transitions is a bitset shift-and-OR, so the running time is \[ O\!\left(n \cdot \frac{X}{64}\right), \] and the memory usage is $O(X)$ bits.

    Implementation Notes

    • The DP is done with a manual dynamic bitset for speed.

    • The scaled deadline \[ \left\lfloor \frac{d_i v - 1}{c} \right\rfloor \] must use 64-bit arithmetic.

    • Sorting by deadline and then by smaller $x$ is harmless and keeps equal-deadline handling stable.

Code

C++ solution used for this page.

C++

Clean code view with a raw-file link when you want the original source.

Raw file
#include <bits/stdc++.h>
using namespace std;

namespace {

struct Quest {
    int x;
    int deadline;
};

void solve() {
    int n, v, c;
    cin >> n >> v >> c;

    vector<Quest> quests(n);
    int sum_x = 0;
    long long base_xp = 0;

    for (int i = 0; i < n; ++i) {
        int x, d;
        cin >> x >> d;
        long long latest_start = (1LL * d * v - 1) / c;
        quests[i] = {x, int(latest_start + x)};
        sum_x += x;
        base_xp += x;
    }

    sort(quests.begin(), quests.end(), [](const Quest& a, const Quest& b) {
        if (a.deadline != b.deadline) {
            return a.deadline < b.deadline;
        }
        return a.x < b.x;
    });

    vector<unsigned long long> reachable((sum_x >> 6) + 1, 0);
    reachable[0] = 1ULL;
    int max_reachable = 0;

    for (const Quest& quest : quests) {
        int shift = quest.x;
        int limit = min(sum_x, quest.deadline);
        int target_max = min(limit, max_reachable + shift);
        int word_shift = shift >> 6;
        int bit_shift = shift & 63;

        for (int word = target_max >> 6; word >= word_shift; --word) {
            unsigned long long value = reachable[word - word_shift] << bit_shift;
            if (bit_shift != 0 && word - word_shift - 1 >= 0) {
                value |= reachable[word - word_shift - 1] >> (64 - bit_shift);
            }
            reachable[word] |= value;
        }

        reachable[target_max >> 6] &= (~0ULL) >> (63 - (target_max & 63));
        max_reachable = target_max;
    }

    int best_bonus_sum = 0;
    for (int s = max_reachable; s >= 0; --s) {
        if ((reachable[s >> 6] >> (s & 63)) & 1ULL) {
            best_bonus_sum = s;
            break;
        }
    }

    cout << base_xp + 1LL * (c - 1) * best_bonus_sum << '\n';
}

}  // namespace

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    solve();
    return 0;
}

Source Files and Assets

Raw files are still available here when you want the original TeX, C++, or statement assets.

Show raw files