Динамика (19 ноября 2024)
- (повторение) bitset
- Подробный рассказ bitset: что может, как это делает.
- Оптимизируем рюкзак до nS/w
- (новое) Пояснение про асимптотику: w=64, но также w ≥ logn, значит можно писать под O(...)
- (новое) Оптимизируем в НОП память до n2/w (восстановление ответа всё ещё доступно).
- (повторение) Напоминание про НОП, повторение Хиршберга
- Мы умеем получать O(n) память без восстановления ответа, храня два последних слоя (идея слоёв ещё нужна)
- Мы умеем получать O(n) память с восстановлением ответа: алгоритм Хиршберга
- НВП (Наибольшая Возрастающая Подпоследовательность) за nlogn
- (разбор дз) НВП ↔ НОП за O(n)
- Динамика за O(n2): len[i] → max, конец ровно в i, переход i → j
- nlogn: minEnd[len]
- Код O(nlogn):
for (int x : a) *lower_bound(last, last + n, x) = x
- Восстановление ответа
- (новое) DP − измельчение перехода, выбор состояния, функции (на примере задачи про погрузку корабля)
- Условие: есть массив грузов (a[i]), по очереди грузятся корабли (все размера W), корабль = взять что-то слева + взять что-то справа. Погрузить всё мин числом кораблей.
- Переинтепретация: идём с двух краёв, набираем рюкзаки, разбить предметы на минимальное число рюкзаков.
- [skipped] Решение #1: O(n4), k[L,R] → min, переход = перебрать префикс и суффикс
- Решение #2: O(n3), k[L,R] → min, переход = перебрать только префикс, суффикс вторым указателем
- Решение #3: O(n3), w[L,R,k] → min, переход или закончить погрузку, или взять ещё один предмет (сделали измельчение)
- Решение #4: O(n2), pair [L,R] → min, переход или закончить погрузку, или взять ещё один предмет (перенесли часть состояния в функцию)
- Заметим, что к решению #4 применимы оптимизации по памяти (и "хранить последние две строки" и алгоритм Хиршберга)
- (На практику!) Ещё одна история про выбор состояния: рюкзак со стоимостями, веса большие, стоимости маленькие.
− Перерыв −
- (закрепляем практику) DP и возведение матрицы в степень
- Пути в графе (количество путей длины ровно k): объяснение без матриц, вводим понятие "умножение матриц".
- Числа фибоначчи (начали на практике).
- Рекуррентные соотношения за O(k3 log n) (начали на практике)
- Реклама: рекуррентные соотношения можно решать и за O(k log k log n)
- (новое) DP и два указателя (серверы за O(n2)) без док-ва
- Постановка задачи: разбить массив длины n на k отрезков
- Естественная динамика minCost[k,n], переход − отделить k-й отрезок, внутри перехода ставим оптимальный сервер на отрезок
- Постановка оптимального сервера на отрезок − взвешенная медиана. Можно сделать предподсчёт server[l,r]
- Также известна стоимость отрезка [l,r], она выражается через частичные суммы весов prefixSum[r+1], prefixSum[l], prefixSum[server[l,r]]
- Получили решение за O(n2k).
- Оптимизация Кнута: заменим перебор 0 ≤ p[k,n] ≤ n-1 на p[k-1,n] ≤ p[k,n] ≤ p[k,n+1]
- Разделяй и властвуй: используем p[k,n] ≤ p[k,n+1], делаем переход p[k] → p[k+1] на отрезке [l,r]: p[k,l] ≤ p[k,i] ≤ p[r,i], посчитаем за O(r-l) p[k,m], сделаем 2 рекурсивных вызова.