Автор проблеми: | Хасан Салех (MathModel) |
Підготовлено: | Хасан Салех (MathModel) |
Редаговано: | Хасан Салех (MathModel) |
Розв'язок
Нам дано перестановку , і за один хід ми можемо застосувати -цикл на індексах i<j<k в будь-якому напрямку:
Наша мета - досягти ідентичної перестановки, використовуючи мінімальну кількість ходів.
Зверніть увагу, що -цикл є парною перестановкою, оскільки
Отже, парність перестановки ніколи не змінюється.
Нехай перестановка розкладається на неперетинних циклів (включаючи фіксовані точки). Ми знаємо, що
Отже, якщо (n-c) непарне, перестановка є непарною, і досягти ідентичності неможливо. У цьому випадку відповідь - .
Тепер припустимо, що (n-c) парне.
Ми можемо обробляти кожен цикл незалежно, тому достатньо зрозуміти, скільки операцій потрібно, щоб розбити один цикл довжини .
Зверніть увагу, що одна операція -цикла може збільшити кількість циклів максимум на . Щоб перетворити цикл довжини у фіксованих точок, нам потрібно збільшити кількість циклів на (l-1), тому кількість ходів становить щонайменше
Тепер ми покажемо, що ця межа досяжна.
Якщо непарне, сам цикл є парним. Ми можемо використовувати лише елементи цього циклу, і кожна операція збільшує кількість циклів на . Після (l-1)/2 ходів цикл повністю фіксується.
Якщо парне, цикл є непарним і не може бути зафіксований самостійно. Однак, оскільки (n-c) парне, існує інший цикл парної довжини (або додаткові елементи) для парування. Використовуючи це, цикл все ще може бути зафіксований за точно операцій.
Отже, цикл довжини вносить точно
ходів.
Підсумовуючи по всіх циклах з довжинами l_1,l_2,\dots,l_c, ми отримуємо:
Якщо (n-c) непарне, виведіть , в іншому випадку виведіть значення вище.
Складність .
for _ in range(int(input())):
n=int(input())
p=[0]+list(map(int,input().split()))
vis=[0]*(n+1)
ans=0
c=0
for i in range(1,n+1):
if vis[i]: continue
c+=1
cur=i
l=0
while not vis[cur]:
vis[cur]=1
cur=p[cur]
l+=1
ans+=l//2
print(-1 if ((n-c)&1) else ans)