Official

C - Inverse of Permutation Editorial by Nyaan


この問題のように順列 \(P = (p_1, p_2,\dots, p_N)\) に対して \(q_{p_i} = i\) を満たす順列 \(Q = (q_1, q_2, \dots,q_N)\) のことを 逆置換 と呼びます。

逆置換を使用するアルゴリズムは実は数多くあります。 例えば \(P\) があったときに 「 \(i\)\(P\) の中で何番目にありますか?」というクエリがたくさん飛んでくるケースを考えましょう。このとき、単純に \(P\) を前から走査すると \(\mathrm{O}(N)\) かかってしまいますが、逆置換をあらかじめ計算しておくと \(q_i\) が答えになるのでクエリを \(\mathrm{O}(1)\) で処理することができます。

実装方法はわかってしまえばシンプルで、 \(1 \leq i \leq N\) に対して Q[P[i]] = i とすればよいです。
\(Q\) を昇順に埋めていないので少し非直感的ですが、このアルゴリズムによって \(P\) の要素が取り得るすべての値 \(i\) \((1 \leq i \leq N)\) に対して \(Q_i\) を埋めることができていることから正当性が確かめられます。

別解として連想配列などのデータ構造を使用しても AC することができます。

C++. Python による実装は以下の通りです。

  • C++
#include <iostream>
#include <vector>
using namespace std;

#define rep(i, n) for (int i = 0; i < (n); i++)

int main() {
  int N;
  cin >> N;
  vector<int> p(N), q(N);
  for (auto& x : p) cin >> x, --x;
  rep(i, N) q[p[i]] = i;
  rep(i, N) cout << q[i] + 1 << " \n"[i == N - 1];
}
  • Python
N = int(input())
P = [0] + list(map(int, input().split()))
Q = [-1] * (N + 1)
for i in range(1, N + 1):
  Q[P[i]] = i
print(" ".join(map(str, Q[1:])))

posted:
last update: