公開日 :
更新日 :
順列 \(P\) の「位置 → 値」の矢印を逆向きにした「値 → 位置」の対応が逆順列。
\(Q[P[i]] = i\) の \(1\) 行で \(O(N)\) で作れて、「値 \(v\) はどこにある?」に \(O(1)\) で答えられる。
順列 \(P = (P_1, \dots, P_N)\) の逆順列 \(Q\) は、次を満たす順列。
たとえ話 : \(P\) は「座席 \(i\) に座っている人」、 \(Q\) は「人 \(v\) が座っている座席」。
同じ座席表を、座席から見るか、人から見るかの違い。
\(P = (3, 1, 4, 2)\)
| 位置 \(i\) | \(1\) | \(2\) | \(3\) | \(4\) |
| \(P_i\) | \(3\) | \(1\) | \(4\) | \(2\) |
値 \(1\) は位置 \(2\)、値 \(2\) は位置 \(4\)、値 \(3\) は位置 \(1\)、値 \(4\) は位置 \(3\) なので、
\(Q = (2, 4, 1, 3)\)
確認 : \(P_{Q_1} = P_2 = 1\), \(P_{Q_2} = P_4 = 2\), \(P_{Q_3} = P_1 = 3\), \(P_{Q_4} = P_3 = 4\)
vector<int> Q(n + 1);
for (int i = 1; i <= n; i++) {
Q[P[i]] = i; // 値 P[i] の位置は i
}「逆順列」という用語を使わず、条件式で定義することが多い。
| 書き方 | 意味 |
| \(P={P’_i} = i\) を満たす \(P’\) | \(P’\) は \(P\) の逆順列 |
| \(P’={P_i} = i\) を満たす \(P’\) | 同じく逆順列 |
| \(P_j = i\) となる \(j\) を \(Q_i\) とする | 値から位置を引く、を言語化 |
| \(i\) が \(P\) の何番目にあるか | 日常語よりの書き方 |
見抜くコツ: \(X_{Y_i} = i\) の形(添字の中に別の順列があって \(i\) に等しい)を見たら、\(X\) と \(Y\) は逆順列どうし。
コードでは \(Y[X[i]] = i\) に直せる。
「この操作を \(2\) 回やるとどうなる?」と自問する。
反転・補集合・逆順列・転置などは \(2\) 回で元に戻る。
こういう操作は実際に実行せず、フラグで「今どちらが本物か」を管理できないか疑う。