Когда у нас есть только запросы и обмены (без обновлений диапазона), задача становится тривиальной. Мы можем поддерживать простой массив и выполнять операции напрямую:
A[i] за O(1)A[i] и A[j] за O(1)Этот подход прост, так как нам не нужно обрабатывать обновления диапазона.
Эта подзадача требует эффективных обновлений диапазона и точечных запросов - классическая задача, решаемая с помощью техники массива разностей:
Поддерживаем массив разностей в дереве Фенвика, где мы храним diff[i] = A[i] - A[i-1].
Ключевое понимание: Если diff[i] = A[i] - A[i-1], то A[i] = diff[1] + diff[2] + ... + diff[i] (префиксная сумма).
Операции:
diff[l] += xdiff[r+1] -= xС небольшими ограничениями на вход, наивный подход работает идеально:
A[i] за O(1)A[i] и A[j] за O(1)Это грубое решение приемлемо, так как Q·N ≤ 4·10^6.
Полная задача требует эффективной обработки как обменов, так и обновлений диапазона. Проблема заключается в сочетании техники массива разностей с обменами.
Подход: Дерево Фенвика с массивом разностей
Мы поддерживаем BIT, хранящий массив разностей: diff[i] = A[i] - A[i-1].
Операции:
Тип 1 (Запрос позиции i):
A[i] = prefix_sum(i) = сумма diff[1..i]Тип 3 (Обновление диапазона [l, r] на x):
Тип 2 (Обмен позиций l и r) - Ключевое понимание:
val_l = get(l), val_r = get(r)d = val_l - val_rdiff[l] -= d (уменьшить A[l] на d)diff[l+1] += d (отменить эффект после позиции l)diff[r] += d (увеличить A[r] на d)diff[r+1] -= d (отменить эффект после позиции r)Почему это работает для обменов: Используя массив разностей, мы можем изменить одно положение, не затрагивая другие, обновляя в позиции i и отменяя в позиции i+1.