Skip to content

USACO 2015 December Contest Gold Division - High Card Low Card (Gold)#

Problem link: here

Solution Author: Stefan Dascalescu

Problem Solution#

We can solve this problem greedily.

You can assume Bessie uses only her largest \(N/2\) cards in the first half (high-wins rounds) and only her smallest \(N/2\) cards in the second half (low-wins rounds).

For the first half (high-wins): for Elsie’s card \(e\), if possible play the smallest Bessie card \(> e\) (wins and preserves larger cards); otherwise, discard your smallest card (you can’t win this round anyway).

For the second half (low-wins): for Elsie’s card \(e\), if possible play the largest Bessie card \(< e\) (wins and preserves even smaller cards for tougher future \(e\)); otherwise, discard your smallest card (no card can be \(< e\)).

Time complexity is \(O(N \log N)\) using ordered sets.

Source code#

The source code in C++ can be seen below.

#include <cstdio>
#include <iostream>
#include <set>
#include <vector>
using namespace std;

void solve() {
    int n;
    cin >> n;
    vector<int> elsie(n);
    vector<bool> used(2 * n + 1, false);
    for (int i = 0; i < n; i++) {
        cin >> elsie[i];
        used[elsie[i]] = true;
    }
    vector<int> bessie;
    bessie.reserve(n);
    for (int x = 1; x <= 2 * n; x++)
        if (!used[x])
            bessie.push_back(x);

    int half = n / 2;
    set<int> lowHalf, highHalf;
    for (int i = 0; i < half; i++)
        lowHalf.insert(bessie[i]);
    for (int i = half; i < n; i++)
        highHalf.insert(bessie[i]);

    int ans = 0;

    for (int i = 0; i < half; i++) {
        int e = elsie[i];
        auto it = highHalf.upper_bound(e);
        if (it != highHalf.end()) {
            ans++;
            highHalf.erase(it);
        } else {
            highHalf.erase(highHalf.begin());
        }
    }

    for (int i = half; i < n; i++) {
        int e = elsie[i];
        auto it = lowHalf.lower_bound(e);
        if (it == lowHalf.begin()) {
            if (!lowHalf.empty()) {
                auto jt = lowHalf.end();
                --jt;
                lowHalf.erase(jt);
            }
        } else {
            --it;
            ans++;
            lowHalf.erase(it);
        }
    }

    cout << ans << '\n';
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    freopen("cardgame.in", "r", stdin);
    freopen("cardgame.out", "w", stdout);

    int t = 1;
    while (t--)
        solve();
    return 0;
}