Изменения

Перейти к: навигация, поиск

Convex hull trick

70 байт добавлено, 21:08, 17 января 2017
Для чего нам нужна эта выпуклая оболочка прямых?
4) Выделим множество точек <math>(x0, y0)</math> , таких что все они принадлежат одной из прямых и при этом нету ни одной прямой <math>y’(x)</math>, такой что <math>y’(x0) < y0</math>. Иными словами возьмем «выпуклую (вверх) оболочку» нашего множества прямых (её еще называют нижней ошибающей множества прямых на плоскости). Назовем ее «<math>y = convex(x)</math>». Видно, что множество точек (x, convex(x)) представляет собой выпуклую вверх функцию.
==Для чего нам нужна эта выпуклая оболочка нижняя ошибающая множества прямых?== Пусть мы считаем динамику для <math>i</math>-го дерева. Его задает <math>x[i]</math>. Итак, нам нужно для данного <math>x[i]</math> найти минимум по всем <math>min_{j=0..i-1}(k[j]*x[i] + b[i]) = min_{j=0..i-1}(y[j](x[i]))</math>. Нетрудно видеть, что это Это выражение есть convex(x[i]). Из монотонности угловых коэффицентов отрезков, задающих выпуклую оболочку, и их расположения по координаты x следует то, что отрезок, который пересекает прямую <math>x = x[i]</math>, можно найти бинарным поиском. Это потребует <math>O(logn)</math> времени на поиск такого j, что dp[i] = k[j] * x[i] + b[j]. Теперь осталось научиться быстро поддерживать множество прямых и быстро добавлять <math>i</math>-ю прямую после того, как мы посчитали <math>b[i] = dp[i]</math>. Название статьи подсказывает, что нужно воспользоваться алгоритмом Воспользуемся идеей алгоритма построения выпуклой оболочки множества точек. Но (внезапно) у нас не точки, а прямые… Но что меняется??? Пусть есть Заведем 2 стека <math>k[] </math> и <math>b[]</math>, которые задают прямые в отсортированном порядкеих угловыми коэффицентами и свободными членами. Пусть пришла новая прямаяРассмотрим ситуацию, когда мы хотим добавить новую (<math>i</math>-тую) прямую в множество. Найдем точки пересечения (по x) с последними 2мя прямыми из стека. Нас будут интересовать только их <math>x</math>-овые координаты. Назовем их <math>xL</math> и <math>xR</math>, соответственно. Если оказалось, что новая прямая пересекает предпоследнюю прямую выпуклой оболочки позже, чем последнюю (xL >= xR), то последнюю можно удалить удалим из нашего множества. Так будем делать, пока либо кол-во прямых в стеке не станет равным 2 или , либо <math>xL</math> не станет меньше <math>xR.</math>
Асимптотика : аналогично обычному алгоритму построения выпуклой оболочки, каждая прямая ровно 1 раз добавится в стек и максимум 1 раз удалится. Значит время работы перестройки выпуклой оболочки займет <math>O(n)</math> суммарно.
Корректность : достаточно показать, что последнюю прямую нужно удалить из множества т.и т.т., когда она последнюю прямую множества наша новая прямая пересекает ее в точке с координатой по оси X, меньшей, чем предпоследнюю.
[[Файл:picture2convexhull.png]]
[[Файл:picture3convexhull.png]]
Анонимный участник

Навигация