Skip to content

USACO 2024 January Contest Silver Division - Cownpetency#

Problem link: here

Solution Author: Stefan Dascalescu

Problem Solution#

We notice that for a prefix of the vector we will need to have a maximum value, and this to be the maximum on a longer prefix up to a certain position, based on the given pair relations.

Thus, we will need to handle this case and, for a position where we put a new element, we must check that it is greater than any element in the prefix in its (if any) longest pair.

If the conditions are met, we have a solution. To modify the maximum of a prefix, we can put a value on the rightmost element equal to 0 on the respective prefix.

For more details, check the source code below.

Source code#

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

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

using ll = long long;
#define pb push_back
#define int ll

void solve() {
    int n, q, c, i, j, a, h, possible_max, mx, idx;

    cin >> n >> q >> c;

    vector<int> score(n + 1);
    for (i = 1; i <= n; i++) {
        cin >> score[i];
    }

    vector<int> same(n + 1), inc(n + 1);
    // same[i] > 0 => pref_mx[i] = pref_mx[i - 1]
    // inc[i] == 1 => pref_mx[i] > pref_mx[i - 1]
    inc[1] = 1;
    while (q--) {
        cin >> a >> h;
        // for a (a, h) i want to have s[h] > max({s[1], s[2], ..., s[a]})
        // s[1] = max(s[1], s[2]) = max({s[1], s[2], s[3]}) = ... = max({s[1], s[2],
        // ..., s[a]})
        same[a + 1]++;
        same[h]--;
        inc[h] = 1;  // h > max({s[1], s[2], ..., s[a]})
    }
    for (i = 1; i <= n; i++) {
        same[i] += same[i - 1];
        if (same[i] > 0 && inc[i] == 1) {
            cout << "-1\n";
            return;
        }
    }

    possible_max = 0;
    for (i = n; i >= 1; i--) {
        if (!same[i]) {
            possible_max = 0;
            continue;
        }
        possible_max = max(possible_max, score[i]);
        if (score[i - 1] == 0) {  // unknown yet
            continue;
        }
        // propagate
        if (possible_max > score[i - 1]) {
            same[i - 1] = same[i];
        }

        if (same[i] > 0 && inc[i] == 1) {
            cout << "-1\n";
            return;
        }
        if (same[i - 1] > 0 && inc[i - 1] == 1) {
            cout << "-1\n";
            return;
        }
    }

    possible_max = 0;
    for (i = 1; i <= n; i++) {
        mx = max(score[i], 1LL);  // score[i] = 0 => unknown
        if (inc[i]) {
            // inc[i] => pref_mx[i] > pref_mx[i - 1]
            mx = max(mx, possible_max + 1);
        }

        j = i;
        // same[j + 1] => pref_mx[j + 1] = pref_mx[j]
        while (j <= n - 1 && same[j + 1] > 0) {
            mx = max(mx, score[++j]);
        }
        if (score[i] == 0) {
            // it is unknown
            if (max(mx, possible_max) == mx) {
                score[i] = mx;
            } else {
                score[i] = 1;  // for the lexicographically smallest string
            }
        }
        for (idx = i + 1; idx <= j; idx++) {
            if (score[idx] > 0) {
                continue;
            }
            score[idx] = 1;  // lexicographically smallest
        }
        possible_max = max(possible_max, mx);
    }

    if (possible_max > c) {
        cout << "-1\n";
        return;
    }

    vector<int> pref_mx(n + 1, 0);
    for (i = 1; i <= n; i++) {
        pref_mx[i] = max(pref_mx[i - 1], score[i]);

        if (same[i] && pref_mx[i] != pref_mx[i - 1]) {
            cout << "-1\n";
        }
        if (inc[i] && pref_mx[i] <= pref_mx[i - 1]) {
            cout << "-1\n";
            return;
        }
    }

    for (i = 1; i <= n; i++) {
        cout << score[i];
        if (i != n) {
            cout << " ";
        }
    }
    cout << "\n";
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    int t;
    cin >> t;
    while (t--) {
        solve();
    }

    return 0;
}