Запити краси перестановки#11732

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

Автор задачі:

Костянтин Денисов

Задачу пiдготував:

Костянтин Денисов, Максим Шведченко

Розбiр написав:

Костянтин Денисов

Група 1. Переберемо всі можливі множини та перевіримо чи можемо відсортувати перестановку для кожної з множин.

Група 2. Розмір мінімальної множини, коли n \le 32 не перевищує (якщо обрати S=\{1, 2, 4, 8, 16\}, то нескладно відсортувати будь-яку перестановку розміром до ), тому можна перебирати лише множини розміру до та перевіряти чи можна відсортувати перестановку.

Група 3. Є три можливі випадки в залежності від мінімального min_S розміру доброї множини у цьому випадку:

  1. min_S=0 \leftrightarrow p_i=i для всіх 0 \le i < n;

  2. min_S=1 \leftrightarrow \exist i: i \neq p_i та \exist x: \forall i (i = p_i \lor i \oplus p_i = x);

  3. Інакше min_S=2.

За допомогою std::map можна підтримувати множину всіх значень i \oplus p_i і перевіряти скільки існує унікальних ненульових значень i \oplus p_i.

Група 4. Нехай в нас є деяка множина , за допомогою якої ми можемо відсортувати нашу перестановки використовуючи операції з умови.

Розгянемо елемент, що стояв на позиції у початковій перестановці. Очевидно, що у тотожній перестановці він знаходиться на позиції p_i. Розглянемо послідовність позицій на яких побував елемент перестановки зі значенням p_i перед тим як перейти на фінальну позицію:

c_0=i \rightarrow c_1 \rightarrow c_2 \rightarrow \ldots \rightarrow c_{k-1} \rightarrow c_k=p_i.

при чому c_{i+1}=c_i \oplus x_i, де x_i \in S для таких , що 0 \le i < k.

Виразимо c_k через c_0: c_k = c_0 \oplus x_0 \oplus x_1 \oplus \ldots \oplus x_{k-1}. Тоді маємо, що

x_0 \oplus x_1 \oplus \ldots \oplus x_{k-1}=c_k \oplus c_0 = i \oplus p_i.

Тобто маємо, що щоб переставити елемент зі значенням p_i на свою позицію необхідно, щоб ксорами елементів множини можна було представити число i \oplus p_i для кожного : 0 \le i < n.

Пригадаємо XOR базис. XOR базис — це мінімальний набір чисел, які можуть представляти будь-яке число заданої множини за допомогою комбінацій XOR. Детальніше можна дізнатися тут.

Нескладно довести, що якщо взяти як XOR базис чисел i \oplus p_i побудований алгоритмом наведеним нижче, то це і буде одна з множин мінімального розміру, якою можна відсортувати задану перестановку.

vector <int> basis;

void add (int x) {
    for (int i : basis) {
        x = min(x, x ^ i);
    }
    if (x) {
        for (int &i : basis) {
            i = min(i, i ^ x);
        }
        basis.push_back(x);
    }
}

Тоді відповіддю на кожен запит є розмір XOR базису побудованого на числах i \oplus p_i.

Тоді після кожного запиту можемо за O(n \cdot log n) порахувати розмір XOR базису та вивести його. Складність розв'язку: O(q \cdot n \cdot log n).

Група 5. За домогою дерева відрізків можна підримувати XOR базис масиву за O(log^3(n)) на запит. В кожній вершині будемо зберігати XOR базис чисел i \oplus p_i за які відповідає відповідний сегмент дерева відрізків.

Об'єднувати два базиси можна в лоб за O(log^2(n)). Тоді операція оновлення буде працювати за O(log^3(n)).

Група 6. Коли \beta=0, то ми знаємо всі запити наперед. До XOR базису ми можемо додавати елементи. Але, на жаль, не можемо видаляти. Маючи все це можемо використати цю техніку, яка дозволяє видаляти із структури, в яку можемо додавати, якщо запити дано наперед.

Група 7.

Як підтримувати XOR базис в онлайні за O(\log^2{n}) на запит можна дізнатися за посиланням.