Мінімальний трійник#12307

Мінімальний трійник (Розбір)

Автор проблеми:

Хасан Салех (MathModel)

Підготовлено:

Хасан Салех (MathModel)

Редаговано:

Хасан Салех (MathModel)

Розв'язок

Нам дано перестановку , і за один хід ми можемо застосувати -цикл на індексах i<j<k в будь-якому напрямку:

(p_i,p_j,p_k)\leftarrow(p_j,p_k,p_i) \quad\text{або}\quad (p_i,p_j,p_k)\leftarrow(p_k,p_i,p_j).

Наша мета - досягти ідентичної перестановки, використовуючи мінімальну кількість ходів.

Зверніть увагу, що -цикл є парною перестановкою, оскільки

(a\,b\,c)=(a\,c)(a\,b).

Отже, парність перестановки ніколи не змінюється.

Нехай перестановка розкладається на неперетинних циклів (включаючи фіксовані точки). Ми знаємо, що

\operatorname{sgn}(p)=(-1)^{n-c}.

Отже, якщо (n-c) непарне, перестановка є непарною, і досягти ідентичності неможливо. У цьому випадку відповідь - .

Тепер припустимо, що (n-c) парне.

Ми можемо обробляти кожен цикл незалежно, тому достатньо зрозуміти, скільки операцій потрібно, щоб розбити один цикл довжини .

Зверніть увагу, що одна операція -цикла може збільшити кількість циклів максимум на . Щоб перетворити цикл довжини у фіксованих точок, нам потрібно збільшити кількість циклів на (l-1), тому кількість ходів становить щонайменше

\left\lceil \frac{l-1}{2} \right\rceil = \left\lfloor \frac{l}{2} \right\rfloor.

Тепер ми покажемо, що ця межа досяжна.

  • Якщо непарне, сам цикл є парним. Ми можемо використовувати лише елементи цього циклу, і кожна операція збільшує кількість циклів на . Після (l-1)/2 ходів цикл повністю фіксується.

  • Якщо парне, цикл є непарним і не може бути зафіксований самостійно. Однак, оскільки (n-c) парне, існує інший цикл парної довжини (або додаткові елементи) для парування. Використовуючи це, цикл все ще може бути зафіксований за точно операцій.

Отже, цикл довжини вносить точно

\left\lfloor \frac{l}{2} \right\rfloor

ходів.

Підсумовуючи по всіх циклах з довжинами l_1,l_2,\dots,l_c, ми отримуємо:

\text{відповідь} = \sum_{i=1}^{c} \left\lfloor \frac{l_i}{2} \right\rfloor.

Якщо (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)