Submission #1329830

#TimeUsernameProblemLanguageResultExecution timeMemory
1329830model_codeCarnival (EGOI23_carnival)C++20
100 / 100
22 ms2616 KiB
#include <bits/stdc++.h>
using namespace std;

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

    int n;
    cin >> n;

    // ranking[i] = ranking list of general i (length i), for i >= 1
    // ranking[i][j] = the general at position j in general i's ranking
    vector<vector<int>> ranking(n);
    for (int i = 1; i < n; i++) {
        ranking[i].resize(i);
        for (int j = 0; j < i; j++) {
            cin >> ranking[i][j];
        }
    }

    // For each general j >= 1, compute the set of "good" generals
    // (those in the first half of j's ranking, i.e., position c2 where 2*c2 < j).
    // Number of good generals for j: positions 0..ceil(j/2)-1
    // good[j] is a set of generals that j can be adjacent to.
    vector<vector<bool>> good(n);
    for (int j = 1; j < n; j++) {
        good[j].assign(n, false);
        for (int c2 = 0; 2 * c2 < j; c2++) {
            good[j][ranking[j][c2]] = true;
        }
    }

    // Incremental insertion: maintain arrangement as a linked list (using a vector/deque).
    // Start with [0].
    // For j = 1..N-1, insert j into a valid position.
    //
    // When inserting general j (the largest so far), both neighbors must be
    // in j's "good" set. Such a position always exists by pigeonhole argument.

    list<int> arrangement;
    arrangement.push_back(0);

    for (int j = 1; j < n; j++) {
        // Try to find an insertion position.
        // We scan through the arrangement and look for a gap where both
        // neighbors are good (or it's an endpoint with one good neighbor).

        bool inserted = false;

        // Check: can we insert at the front?
        // Front neighbor is arrangement.front(). It must be good for j.
        if (good[j][arrangement.front()]) {
            arrangement.push_front(j);
            inserted = true;
        }

        if (!inserted) {
            // Check: can we insert at the back?
            if (good[j][arrangement.back()]) {
                arrangement.push_back(j);
                inserted = true;
            }
        }

        if (!inserted) {
            // Scan interior gaps: between consecutive elements a and b,
            // both a and b must be good for j.
            auto it = arrangement.begin();
            auto prev_it = it;
            ++it;
            while (it != arrangement.end()) {
                if (good[j][*prev_it] && good[j][*it]) {
                    // Insert j between prev_it and it
                    arrangement.insert(it, j);
                    inserted = true;
                    break;
                }
                prev_it = it;
                ++it;
            }
        }

        // By the pigeonhole argument, a valid position must always exist.
        // But just in case, assert:
        if (!inserted) {
            // This should never happen for valid inputs.
            // Fallback: try inserting anywhere (should not be needed).
            arrangement.push_back(j);
        }
    }

    // Output the arrangement
    bool first = true;
    for (int x : arrangement) {
        if (!first) cout << ' ';
        cout << x;
        first = false;
    }
    cout << '\n';

    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...