Обернена перестановка#1788

Обернена перестановка (Розбір)

Перестановкою порядку називається послідовність p = (p[1], p[2], \ldots, p[n]), в якій кожне число від до зустрічається рівно один раз. Зручно розглядати перестановку як відображення, що переводить число у число : i \to p[i].

Оберненою до перестановки називається перестановка p^{-1}, яка повертає кожне число на своє місце: якщо переводить у , то p^{-1} переводить назад у . Іншими словами, для всіх виконується рівність:

p^{-1}[p[i]] = i

Ця рівність одразу дає алгоритм: число має стояти на позиції оберненої перестановки. Переберемо всі від до і для кожного з них виконаємо присвоєння pi[p[i]] = i, де масив зберігає обернену перестановку.

Кожна позиція масиву заповнюється рівно один раз. Дійсно, значення p[1], p[2], \ldots, p[n] попарно різні та охоплюють усі числа від до , тому індекси також попарно різні та охоплюють усі позиції від до .

Дворядковий запис. Перестановку часто записують у два рядки: у верхньому рядку стоять числа 1, 2, \ldots, n, а під кожним числом стоїть значення . Щоб отримати обернену перестановку, достатньо поміняти рядки місцями та відсортувати стовпці за зростанням верхнього рядка.

Приклад

Розглянемо перестановку з прикладу. Запишемо її та обернену до неї перестановку у дворядковому вигляді:

p = \begin{pmatrix} 1 & 2 & 3 \\ 2 & 3 & 1 \end{pmatrix}, \qquad p^{-1} = \begin{pmatrix} 1 & 2 & 3 \\ 3 & 1 & 2 \end{pmatrix}

Знайдемо p^{-1} за формулою pi[p[i]] = i:

pi[p[1]] = pi[2] = 1, \quad pi[p[2]] = pi[3] = 2, \quad pi[p[3]] = pi[1] = 3

Отримуємо p^{-1} = (3, 1, 2). Дворядковий запис дає той самий результат: поміняв рядки перестановки місцями, отримуємо стовпці , , . Відсортувавши їх за верхнім рядком, отримуємо нижній рядок .

На малюнку перестановка зображена у вигляді стрілок i \to p[i]. В оберненій перестановці всі стрілки вказують у протилежному напрямку: p[i] \to i.

Реалізація алгоритму

Масив зберігає вхідну перестановку, а масив зберігає обернену перестановку.

#define MAX 20010
int p[MAX], pi[MAX];

Зчитаємо вхідну перестановку.

scanf("%d",&n);
for(i = 1; i <= n; i++)
  scanf("%d",&p[i]);

Обчислимо обернену перестановку.

for(i = 1; i <= n; i++)
  pi[p[i]] = i;

Виведемо обернену перестановку.

for(i = 1; i <= n; i++)
  printf("%d ",pi[i]);
printf("\n");

Реалізація мовою Python

Список зберігає вхідну перестановку, а список зберігає обернену перестановку. Зчитаємо вхідні дані.

n = int(input())
p = [0] + list(map(int, input().split()))
pi = [0] * (n + 1)

Обчислимо обернену перестановку.

for i in range(1, n + 1):
  pi[p[i]] = i

Виведемо обернену перестановку.

for i in range(1, n + 1):
  print(pi[i], end=" ")
print()