Official

C - Lining Up 2 Editorial by en_translator


Consider the following sequence \((B _ i) _ {1\leq i\leq N}\):

\[B _ i=\left\lbrace\begin{matrix}j&(A _ j=i)\hphantom{\text{otherwise}}\\-1&(\text{otherwise})\hphantom{A _ j=i}\end{matrix}\right..\]

This sequence satisfies “behind person \(i\) is person \(B_i\) (or \(-1\) if no one is behind).”

Once we find these \(B _ i) _ {1\leq i\leq N}\), using \(x\) satisfying \(A _ x=-1\), the people in the line can be enumerated as person \(x,\) person \(B _ x,\) person \(B _ {B _ x},\) person \(B _ {B _ {B _ x}},\ldots,\) and person \(B _ {B _ {{}_{\ddots _ {B _ x}}}}\).

Thus, it is sufficient to find the sequence \((B _ i)\) and the frontmost person, and then appropriately repeat \(x\leftarrow B _ x\).

Sample code follows. We use the property that, if no one is behind person \(i\), the value \(B _ i\) can be freely chosen (as long as it does not collide with anything else).

#include <iostream>
#include <vector>

int main() {
    using namespace std;
    unsigned N;
    cin >> N;

    vector<unsigned> B(N, N); // B[i] := person behind person i (or N if nobody is behind)
    unsigned front;

    for(unsigned i = 0; i < N; ++i){
        int A;
        cin >> A;
        --A; // Make it 0-based numbering
        if(A < 0)
            front = i;
        else
            B[A] = i; // Behind person i is person A ⇔ behind person A is person i
    }

    while(front < N){ // repeatedly inspect the person behind the current one, until it reaches N (=nobody is behind)
        cout << front + 1 << " ";
        front = B[front];
    }
    cout << endl;

    return 0;
}

posted:
last update: