C - Sugoroku Destination 解説 by en_translator
Once the piece reaches a cell \(i\) with \(A _ i=i\), it does no longer move from there. Until then the piece advances by at least one cell in one move, but such an event occurs at most \((N-i)\) times starting from cell \(i\). Since \(N\leq10 ^ {100}\), “performing the operation \(10 ^ {100}\)” is essentially “performing the operation until the piece can no longer move.”
Therefore, the following algorithm outputs a correct answer:
- For \(i=1,2,\ldots,N\) in order, do the following:
- Initialize \(\operatorname{ans}\leftarrow i\).
- While \(\operatorname{ans}\neq A _ {\operatorname{ans}}\), repeatedly set \(\operatorname{ans}\leftarrow A _ {\operatorname{ans}}\).
- Print \(\operatorname{ans}\).
The repetition in step 2. is iterated at most \(N-i\) times for each \(i\). Thus, the worst time complexity of this algorithm is \(\Theta(N ^ 2)\), so implementing and submitting this algorithm will result in exceeding the time limit.
However, if you try to find \((\operatorname{ans} _ 1,\operatorname{ans} _ 2,\ldots,\operatorname{ans} _ N)\) from the bottom, the later results can be reused.
- For \(i=N,N-1,\ldots,2,1\), do the following:
- Initialize \(\operatorname{ans} _ i\leftarrow i\).
- If \(\operatorname{ans} _ i\neq A _ {\operatorname{ans} _ i}\), set \(\operatorname{ans} _ i\leftarrow\operatorname{ans} _ {A _ i}\).
- For each \(i=1,2,\ldots,N\), print \(\operatorname{ans} _ i\).
This way, the worst time complexity is reduced to \(\Theta(N)\), which is fast enough to find the answer.
The following is sample code:
#include <iostream>
#include <vector>
#include <ranges>
int main() {
using namespace std;
int N;
cin >> N;
vector<int> A(N);
for (auto&& a : A) {
cin >> a;
--a; // turn it into 0-based indexing
}
vector<int> ans(N);
for (int i : views::iota(0, N) | views::reverse) { // Find the final destination in descending order
if (i == A[i]) { // if you are stuck at there
ans[i] = i; // that cell is the answer
} else { // if you will leave
ans[i] = ans[A[i]]; // the answer starting from the cell you moved into is the answer
}
}
for (int a : ans) {
// turn to 1-based indexing and print
cout << a + 1 << " ";
}
cout << endl;
return 0;
}
投稿日時:
最終更新: