Загрузил rodzher.zet

Практика по алгоритмам Сортировка, точки экстремумы

Реклама
SPb HSE, 1 курс, осень 2019/20
Практика по алгоритмам #6
Сортировки, точки-экстремумы
10 октября
Собрано 17 октября 2019 г. в 19:14
Содержание
1. Сортировки и поиск
1
2. Задачи про поиск точки
1
3. Дополнительные задачи
2
4. Разбор задач практики
4.1. Задачи про поиск точки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2. Дополнительные задачи . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
4
6
5. Домашнее задание
5.1. Обязательная часть . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2. Дополнительная часть . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8
8
9
6. Разбор домашнего задания
10
6.1. Обязательная часть . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
6.2. Дополнительная часть . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Алгоритмы, осень 2019/20
Практика #6. Сортировки, точки-экстремумы.
Сортировки и поиск
1. Пирожки
Робот Иван Семеныч пробует пирожки. Содержимое пирожков делится на три типа. Всего
пирожков 𝑛. Каждый пирожок можно попробовать не более одного раза. Пирожки можно
менять местами. Память у робота маленькая, 𝒪(log 𝑛) бит. Помогите Ивану Семенычу отсортировать пирожки по типу: сначала первый, потом второй, потом третий. Сортировка
должна работать за линейное время.
2. Оптимизация скалярного произведения
Даны два массива 𝑎 и 𝑏 одинаковой длины. Найти такую перестановку 𝑝, что
𝑛
∑︀
a)
𝑎𝑝𝑖 𝑏𝑖 → max;
b)
𝑖=1
𝑛
∑︀
𝑎𝑝𝑖 𝑏𝑖 → min.
𝑖=1
c) Выбрать массив 𝑝 из 𝑘 различных чисел от 1 до 𝑛 так, чтобы
∑︀𝑘
𝑖=1
𝑎𝑝𝑖 𝑏𝑝𝑖 → max.
3. Умный бинпоиск
Пусть мы ищем в сортированном массиве длины 𝑛 такое 𝑘 : 𝑎[𝑘] = 𝑥, тогда бинпоиск работает
за 𝒪(log 𝑛), а линейный поиск за 𝒪(𝑘), что может быть меньше. Научите бинпоиск находить
𝑘 за 𝒪(log 𝑘)!
4. Корни многочлена
a) Найти корень многочлена нечетной степени за 𝒪(𝑛 log 𝑀 ). 𝑛 – степень многочлена.
b) Зная все корни производной, найти все вещественные корни многочлена за 𝒪(𝑛2 log 𝑀 ).
c) Найти все вещественные корни многочлена за 𝒪(𝑛3 log 𝑀 ).
5. Нижняя оценка на два бинпоиска
Докажите, что нельзя сделать и lower_bound, и upper_bound одновременно, используя в
худшем случае меньше чем 2 log2 𝑛 + 𝒪(1) сравнений.
Задачи про поиск точки
Каждую из предложенных задач можно решить за время 𝒪(𝑛), тем не менее решения за линию
от 𝑛 на полилогарифм тоже приветствуются. Для разминки продифференцируйте 𝑥7 + 4𝑥3 ,
найдите за 𝒪(𝑛) площадь пересечения 𝑛 прямоугольников со сторонами параллельными осям
координат, поймите как выглядит на плоскости множество точек {max(|𝑥|, |𝑦|) 6 𝑑}, как оно
выглядит после поворота на 45, опишите новую фигуру формулой.
1. Точки на прямой
Даны 𝑛 точек на прямой 𝑥𝑖 . Найти точку 𝑥* :
∑︀
a)
(𝑥𝑖 − 𝑥* )2 → min
𝑖
∑︀
b)
|𝑥𝑖 − 𝑥* | → min
𝑖
c) max |𝑥𝑖 − 𝑥* | → min
𝑖
d) max(𝑥𝑖 − 𝑥* )2 → min
𝑖
1/12
Алгоритмы, осень 2019/20
Практика #6. Сортировки, точки-экстремумы.
2. Точки на плоскости
Даны 𝑛 точек на плоскости (𝑥𝑖 , 𝑦𝑖 ). Найти точку (𝑥* , 𝑦 * ):
[︁
]︁
a) max max(|𝑥𝑖 − 𝑥* |, |𝑦𝑖 − 𝑦 * |) → min
𝑖 [︁
]︁
b) max |𝑥𝑖 − 𝑥* | + |𝑦𝑖 − 𝑦 * | → min
𝑖
]︁
∑︀[︁
c)
(𝑥𝑖 − 𝑥* )2 + (𝑦𝑖 − 𝑦 * )2 → min
𝑖
]︁
∑︀[︁
d)
|𝑥𝑖 − 𝑥* | + |𝑦𝑖 − 𝑦 * | → min
𝑖
]︁
∑︀[︁
e)
max(|𝑥𝑖 − 𝑥* |, |𝑦𝑖 − 𝑦 * |) → min
𝑖
3. Точки с весами
На прямой расположено
𝑛 точек
]︁ 𝑝1 , 𝑝2 , . . . , 𝑝𝑛 . Каждая точка имеет вес 𝑤𝑖 > 0. Требуется
∑︀ [︁
найти точку 𝑞 :
𝑖 𝑤𝑖 · |𝑝𝑖 − 𝑞| → min.
(*) Решить за 𝒪(𝑛).
Дополнительные задачи
1. Еще ускорение SiftDown
Модифицируйте операцию SiftDown для бинарной кучи так, чтобы она по-прежнему работала за 𝒪(log 𝑛), но при этом делала лишь log2 𝑛 + 𝒪(log* 𝑛) сравнений.
2. Convex hull
Доказать, что, если мы умеем строить выпуклую оболочку 𝑛 точек на плоскости за время
𝑓 (𝑛), мы умеем сортировать 𝑛 целых чисел за 𝑓 (𝑛).
∑︀
∑︀
3. Hard K-best max ( 𝑘𝑖=1 𝑎𝑝𝑖 )( 𝑘𝑖=1 𝑏𝑝𝑖 ) → max (𝑎𝑖 , 𝑏𝑖 > 0).
∑︀
∑︀
4. Hard K-best min ( 𝑘𝑖=1 𝑎𝑝𝑖 )( 𝑘𝑖=1 𝑏𝑝𝑖 ) → min (𝑎𝑖 , 𝑏𝑖 > 0).
5. Точки на плоскости
[︁
]︁
f) max (𝑥𝑖 − 𝑥* )2 + (𝑦𝑖 − 𝑦 * )2 → min
∑︀𝑖 √︀
g)
(𝑥𝑖 − 𝑥* )2 + (𝑦𝑖 − 𝑦 * )2 → min
𝑖
∑︀
6. Оптимизация min ×
∑︀
Найти отрезок массива, на котором min ×
максимально. 𝒪(𝑛).
a) Все числа положительны.
b) Числа целые, 64-битные. Решение с использованием минимума на отрезке за 𝒪(1).
c) Числа целые, 64-битные. Простое решение со стеком.
7. Коровы и стойла #2
То же самое, только теперь стойла стоят на окружности. Решение за 𝒪(𝑛 log 𝑀 𝐴𝑋).
2/12
Алгоритмы, осень 2019/20
Практика #6. Сортировки, точки-экстремумы.
Разбор задач практики
1. Пирожки
Краткое условие: отсортировать массив одним проходом, используя 𝒪(1) доп.памяти.
Сортировка для 𝑘 типов пирожков за 𝒪(𝑛𝑘) с 𝑘 log2 𝑛 бит доп.памяти на примере 𝑘=3:
Изначально 𝑖1 = 𝑖2 = 𝑖3 = 0.
Поддерживем инвариант: [0, 𝑖1 ) – единицы, [𝑖1 , 𝑖2 ) – двойки, [𝑖2 , 𝑖3 ) – тройки.
Двигаем 𝑖3 , swap-ами ставим 𝑎[𝑖3 ] в нужное место.
2. Оптимизация скалярного произведения
ab) Идея: хотим чтобы максимальный 𝑎𝑖 стоял рядом с максимальным 𝑏𝑗 .
Сортируем пары 𝐴𝑖 = (𝑎𝑖 , 𝑖) по возрастанию.
Если хотим max, сортируем пары 𝐵𝑗 = (𝑏𝑗 , 𝑗) по возрастанию, иначе по убыванию.
Соответствие: 𝐴𝑖 ↔ 𝐵𝑖 . Ответ: 𝑝[𝐴𝑖 .second] = 𝐵𝑖 .second.
Доказательство (транс-неравенство): пробуем менять местами два элемента 𝑎,
𝑎1 𝑏1 + 𝑎2 𝑏2 6 𝑎2 𝑏1 + 𝑎1 𝑏2 ⇔ 𝑎1 (𝑏1 −𝑏2 ) + 𝑎2 (𝑏2 −𝑏1 ) 6 0 ⇔ (𝑎1 −𝑎2 )(𝑏1 −𝑏2 ) 6 0
⇐ (𝑎1 > 𝑎2 ∧ 𝑏1 6 𝑏2 ). Вывод: если 𝑏 отсортирован и 𝑎 не отсортирован, можно поменять
местами
два элемента 𝑎, ответ не ухудшится, число инверсий уменьшится.
∑︀𝑘
𝑎
𝑏
c)
𝑖=1 𝑝𝑖 𝑝𝑖 → max.
Нужна max сумма из 𝑘 элементов массива 𝑐𝑖 = 𝑎𝑖 𝑏𝑖 , берем 𝑘 максимальных 𝑐𝑖 .
Это можно сделать за 𝒪(𝑛 log 𝑛) сортировкой,
можно за 𝒪(𝑛 + 𝑘 log 𝑛) построением кучи и извлечением 𝑘 максимумов,
можно за 𝒪(𝑛) поиском (𝑛−𝑘)-й статистики и выбором всех не меньших ее элементов.
3. Умный бинпоиск
R = 1; while (a[R] < x) R *= 2; за 𝒪(log 𝑘) даст нам 𝑅 < 2𝑘.
Затем фигачим бинпоиск на [0, 𝑅] за 𝒪(log 𝑘)
4. Корни многочлена
a) Пусть для определенности старший коэффициент многочлена будет положительный.
Тогда 𝑓 (𝑥) → +∞ при 𝑥 → +∞, 𝑓 (𝑥) → −∞ при 𝑥 → −∞.
Инвариант бинпоиска: 𝑓 (𝑙) < 0, 𝑓 (𝑟) > 0 ⇒ в [𝑙, 𝑟] всегда есть корень.
На каждом шаге бинпоиска вычисляем 𝑓 (𝑚) за Θ(𝑛), итого 𝒪(𝑛 log 𝑀 ).
Как найти начальные значения 𝑙 и 𝑟?
r = 1; l = -1; while (f(r) < 0) r *= 2; while (f(l) >= 0) l *= 2;
b) Между соседними корнями производной функция монотонна, т.к. производная не меняет
знак ⇒ там не больше одного корня и его можно найти бинпоиском. Еще могут быть корни
справа от max корня производной и слева от min корня (+2 отрезка на рассмотрение).
Степень производной многочлена равна 𝑛−1 ⇒ корней у неё не больше 𝑛−1.
Время работы: 𝒪(𝑛) отрезков, на каждом бинпоиск за 𝒪(𝑛 log 𝑀 ), итого 𝒪(𝑛2 log 𝑀 ).
c) Если 𝑛 = 1, найдём корень за 𝒪(1) (линейное уравнение), иначе посчитаем производную,
рекурсивным вызовом найдём её корни, воспользуемся решением (b).
Как считать производную? 𝑃 (𝑥) = 𝑎𝑛 𝑥𝑛 + · · · + 𝑎1 𝑥 + 𝑎0 ⇒ 𝑃 ′ (𝑥) = 𝑛𝑎𝑛 𝑥𝑛−1 + · · · + 𝑎1 .
Время работы: 𝑇 (𝑛) = 𝑇 (𝑛−1) + 𝑛2 log 𝑀 = 𝒪(𝑛3 log 𝑀 ).
Замечение для самых любопытных.
На практике при наличии кратных корней этот метод не работает из-за погрешности.
3/12
Алгоритмы, осень 2019/20
Практика #6. Сортировки, точки-экстремумы.
Пример: 𝑃 (𝑥) = (𝑥−1)10 ⇒ 𝑃 (1.01) = 10−20 , что не отличимо от нуля даже в long double.
Для борьбы с кратными корнями задачу делят на две – найти кратные корни, как корни
𝐺(𝑥) = 𝑔𝑐𝑑(𝑃 (𝑥), 𝑃 ′ (𝑥)), найти оставшиеся, как корни 𝑃 (𝑥)/𝐺(𝑥).
5. Нижняя оценка на два бинпоиска
Ответом может быть любая пара 𝑖 6 𝑗 ⇒ нужно различать
менее log2 𝑛(𝑛+1)
= 2 log2 𝑛 + 𝒪(1) сравнений.
2
𝑛(𝑛+1)
2
вариантов ⇒ нужно не
4.1. Задачи про поиск точки
1. Точки на прямой
∑︀
* 2
a)
𝑖 (𝑥𝑖 − 𝑥 ) → min.
∑︀
∑︀
𝑥𝑖
*
*
Минимум
в
нуле
производной.
2(𝑥
−
𝑥
)
=
0
⇒
𝑥
=
.
𝑖
𝑛
∑︀
*
b)
𝑖 |𝑥𝑖 − 𝑥 | → min.
Идея: пусть ответ в точке 𝑥, подвигаем чуть-чуть 𝑥, улучшился ли ответ?
Рассмотрим какой-нибудь 𝑥. Пусть слева от него 𝑙 точек, справа 𝑟. ∑︀
Если сдвинем 𝑥 на 𝜀 вправо, не перескочив ни через одну точку, то 𝑖 |𝑥𝑖 − 𝑥| изменится
на (𝑙 − 𝑟)𝜀. Если 𝑙 < 𝑟, движение вправо улучшает. Если 𝑙 > 𝑟, движение влево улучшает.
Итого брать нужно медиану, 𝒪(𝑛).
Если 𝑛 нечётно, медиана = 𝑥⌊𝑛/2⌋ в отсортированном порядке.
Если 𝑛 чётно, медиан две, можно взять любую точку между ними.
c) max𝑖 |𝑥𝑖 − 𝑥* | → min.
𝑛
.
Максимум либо в самой левой, либо в самой правой точке, поэтому 𝑥* = 𝑥1 +𝑥
2
* 2
d) max𝑖 (𝑥𝑖 − 𝑥 ) → min.
𝑛
Задача эквивалентна максимизации |𝑥𝑖 − 𝑥* | ⇒ 𝑥* = 𝑥1 +𝑥
.
2
2. Точки на плоскости
[︁
]︁
a) max𝑖 max(|𝑥𝑖 − 𝑥* |, |𝑦𝑖 − 𝑦 * |) → min.
[︁
]︁
[︁
]︁
*
*
*
*
max𝑖 max(|𝑥𝑖 − 𝑥 |, |𝑦𝑖 − 𝑦 |) = max max𝑖 |𝑥𝑖 − 𝑥 |, max𝑖 |𝑦𝑖 − 𝑦 |
𝑥min +𝑥max
*
max
⇒ координаты
𝑥* и 𝑦 * не
, 𝑦 * = 𝑦min +𝑦
.
2
2
[︁
]︁ зависят друг от друга ⇒ 𝑥 =
b) max𝑖 |𝑥𝑖 − 𝑥* | + |𝑦𝑖 − 𝑦 * | → min.
Предварительные рассуждения.
Бинпоиск по ответу. Внутри бинпоиска нужно уметь проверять, есть ли точка на расстоянии 6 𝑚 от каждой (𝑥𝑖 , 𝑦𝑖 ). Для каждой (𝑥𝑖 , 𝑦𝑖 ) рассмотрим множество точек, находящихся на расстоянии 6 𝑚 по метрике |𝑥−𝑥𝑖 | + |𝑦−𝑦𝑖 |.
Пересекаем эти множества, проверяем, пусто ли пересечение.
Каждое такое множество – квадрат, повернутый на 45∘ к осям координат.
Пересечение множеств – прямоугольник, повернутый на 45∘ .
Из разминки вы умеете пересекать квадраты со сторонами, параллельными осям координат. Повернём плоскость на 45∘ , найдём ответ, повернём его обратно.
Прямое преобразование: (𝑧𝑖 , 𝑡𝑖 ) = (𝑥𝑖 − 𝑦𝑖 , 𝑦𝑖 + 𝑥𝑖 ).
*
* 𝑡* −𝑧 *
Обратное преобразование: (𝑥* , 𝑦 * ) = ( 𝑧 +𝑡
, 2 ).
2
Откуда прямая формула: поворот точки (𝑥, 𝑦) вокруг (0, 0) на 90∘ – это (−𝑦, 𝑥).
Поворот на 45∘ – биссектриса между (𝑥, 𝑦) и (−𝑦, 𝑥), биссектриса получается сложением
4/12
Алгоритмы, осень 2019/20
Практика #6. Сортировки, точки-экстремумы.
векторов. Преобразование
(𝑥𝑖 , 𝑦𝑖 ) → (𝑥𝑖 −𝑦𝑖 , 𝑦𝑖 +𝑥𝑖 ) – это не только поворот, но и растяже√
нием плоскости в 2 раз. Растяжение не влияет на максимизацию.
Заметим, что после поворота и бинпоиск не нужен, получившиеся квадраты – это множества, находящиеся на фиксированном расстоянии от точки по метрике max(|𝑧|, |𝑡|).
Формально: max(|𝑥−𝑦|, |𝑥+𝑦|) = |𝑥| + |𝑦|. То есть, мы свелись к предыдущей задаче:
(︀
)︀
(︀
)︀
max |𝑥* −𝑥𝑖 | + |𝑦 * −𝑦𝑖 | = max max(|𝑧 * −𝑧𝑖 |, |𝑡* −𝑡𝑖 |)
𝑖
𝑖
Решение коротко.
Обозначим 𝑧𝑖 = 𝑥𝑖 + 𝑦𝑖 , 𝑡𝑖 = 𝑥𝑖 − 𝑦𝑖 .
Обозначим 𝑧 * = 𝑥* + 𝑦 * , 𝑡* = 𝑥* − 𝑦 * .
Обозначим 𝑑𝑧𝑖 = 𝑧𝑖 − 𝑧 * , 𝑑𝑡𝑖 = 𝑡𝑖 − 𝑡* , 𝑑𝑥𝑖 = 𝑥𝑖 − 𝑥* , 𝑑𝑦𝑖 = 𝑦𝑖 − 𝑦 * .
Заметим, что
𝑖 + 𝑑𝑦𝑖 |, |𝑑𝑥
[︁ max(|𝑑𝑧𝑖 |,]︁|𝑑𝑡𝑖 |) = max(|𝑑𝑥
[︁
]︁ 𝑖 − 𝑑𝑦𝑖 |) = |𝑑𝑥𝑖 | + |𝑑𝑦𝑖 |.
Тогда max𝑖 |𝑑𝑥𝑖 | + |𝑑𝑦𝑖 | = max𝑖 max(|𝑑𝑧𝑖 |, |𝑑𝑡𝑖 |) .
max
max
, 𝑡* = 𝑡min +𝑡
.
Взяли решение (a) для для точек (𝑧𝑖 , 𝑡𝑖 ), получили 𝑧 * = 𝑧min +𝑧
2
2
𝑧 * +𝑡*
𝑧 * −𝑡*
*
*
Перешли от (𝑧, 𝑡) к (𝑥, 𝑦): 𝑥 = 2 , 𝑦 = 2 .
Главная идея, запомните: max(|𝑑𝑧𝑖 |, |𝑑𝑡𝑖 |) = |𝑑𝑥𝑖 | + |𝑑𝑦𝑖 |, оно же «поворот на 45∘ ».
Алгоритм за 𝒪(𝑛).
1. 𝑧𝑖 = 𝑥𝑖 + 𝑦𝑖 , 𝑡𝑖 = 𝑥𝑖 − 𝑦𝑖
max
max
2. 𝑧 * = 𝑧min +𝑧
, 𝑡* = 𝑡min +𝑡
2
2
𝑧 * +𝑡*
𝑧 * −𝑡*
*
*
3. 𝑥 = 2 , 𝑦 = 2
]︁
∑︀[︁
c)
(𝑥𝑖 − 𝑥* )2 + (𝑦𝑖 − 𝑦 * )2 → min.
𝑖
Сумма
распадается на]︁ независимые суммы по каждой координате. 𝑥* =
[︁
∑︀
|𝑥𝑖 − 𝑥* | + |𝑦𝑖 − 𝑦 * | → min.
d)
∑︀
𝑥𝑖
, 𝑦*
𝑛
=
∑︀
𝑦𝑖
.
𝑛
𝑖
Независимые
суммы по каждой
координате. 𝑥* = 𝑥median , 𝑦 * = 𝑦median .
]︁
∑︀[︁
e)
max(|𝑥𝑖 − 𝑥* |, |𝑦𝑖 − 𝑦 * |) → min.
𝑖
1. Повернуть плоскость на 45∘ , получить задачу (d).
2. Взять решение задачи (d), повернуть полученный ответ обратно.
3. Точки с весами
Идея: пусть ответ в точке 𝑥, подвигаем чуть-чуть 𝑥, улучшился ли ответ?
Рассмотрим какой-нибудь 𝑥, пусть суммарный вес точек слева от 𝑥∑︀
равен 𝑤𝑙 , справа 𝑤𝑟 .
Если сдвинем 𝑥 на 𝜀 вправо, не перескочив ни через одну точку, то
𝑤𝑖 |𝑝𝑖 −𝑥| изменится на
(𝑤𝑙 −𝑤𝑟 )𝜀. Если 𝑤𝑙 < 𝑤𝑟 , движение вправо улучшает. Если 𝑤𝑙 > 𝑤𝑟 , движение влево улучшает.
⇒ нам подойдет самая левая точка такая, что сумма весов слева до неё (включая её саму)
достигает половины от суммарного веса. Так называемая взвешенная медиана.
Найти точку можно за 𝒪(𝑛) тем же алгоритмом (одноветочный Quick Sort), который ищет
медиану. Внутри Qucik Sort теперь нужно смотреть не на число элементов, которые меньше
разбивающего, а на их суммарный вес.
5/12
Алгоритмы, осень 2019/20
Практика #6. Сортировки, точки-экстремумы.
4.2. Дополнительные задачи
1. Еще ускорение SiftDown
log2 𝑛 + 𝒪(log* 𝑛) сравнений.
Пусть мин куча. Спустимся на log 𝑛 − log log 𝑛 вниз, попали в 𝑖, сравним ℎ[𝑖] с нашим 𝑥.
Если ℎ[𝑖] > 𝑥, то бинпоиском за log log 𝑛 побеждаем.
Если ℎ[𝑖] 6 𝑥, то мы за (log 𝑛 − log log 𝑛) + 1 сравнений свели задачу “спуститься вниз на
log 𝑛” к такой же, только спускаться осталось лишь на log log 𝑛, продолжим спуск.
(log 𝑛− log log 𝑛+1) + (log log 𝑛− log log log 𝑛+1) + · · · = log 𝑛 + 𝒪(log* ).
2. Convex hull
Пусть нужно отсортировать числа 𝑥𝑖 . Возьмём точки (𝑥𝑖 , 𝑥2𝑖 ).
Алгоритм построения выпуклой оболочки отсортирует все точки.
∑︀
∑︀
3. Hard K-best max: ( 𝑘𝑖=1 𝑎𝑝𝑖 )( 𝑘𝑖=1 𝑏𝑝𝑖 ) → max.
∑︀
∑︀
Пусть 𝑎𝑖 +𝑏𝑖 = 𝐶 (константа). Тогда какие
бы
𝑘
пар
мы
не
выбрали,
будет
верно
𝑎
+
𝑏𝑖 =
𝑖
∑︀
.
Т.е.
если
существуют
такие
𝑘
𝑎-шек,
мы
𝑘𝐶. Произведение максимально, если
𝑎𝑖 = 𝑘𝐶
2
должны их найти. Это задача о рюкзаке.
4. Hard K-best min: ?
5. Точки [︁на плоскости
]︁
f) max𝑖 (𝑥𝑖 − 𝑥* )2 + (𝑦𝑖 − 𝑦 * )2 → min.
Два вложенных тернарных поиска, по 𝑦 и по 𝑥. 𝒪(𝑛 log2 𝑀 ).
Существует простой вероятностный алгоритм за 𝒪(𝑛) в среднем.
А
√︀ даже детерминированный за 𝒪(𝑛).
∑︀есть
g)
(𝑥𝑖 − 𝑥* )2 + (𝑦𝑖 − 𝑦 * )2 → min.
𝑖
Два вложенных тернарных поиска, по 𝑦 и по 𝑥. 𝒪(𝑛 log2 𝑀 ).
∑︀
6. Оптимизация min ×
Для каждого 𝑖 ищем отрезок [𝐿𝑖 , 𝑅𝑖 ]с максимальной суммой, в котором 𝑎𝑖 = min.
Поиск 𝐿𝑖 и 𝑅𝑖 – независимые задачи, решаются одинаково. Разберем поиск 𝐿𝑖 .
Найдем за 𝒪(𝑛) для каждого элемента ближайший слева меньший его 𝑙𝑖 .
a) Если все числа(︀ положительны, то
)︀ 𝐿𝑖 = 𝑙𝑖 +1.
b) 𝐿𝑖 = max𝑗∈(𝑙𝑖 ,𝑖] 𝑎𝑖 ·(pref 𝑖+1 −pref 𝑗 ) . То есть, если 𝑎𝑖 > 0, min pref 𝑗 , иначе max pref 𝑗 .
c) ∃ структура данных, дающая min/max на полуинтервале (𝑙𝑖 , 𝑖] за 𝒪(1).
Можно проще: давайте по ходу вычисления 𝑙𝑖 помнить min/max между соседними элементами в стеке. Тогда значение для (𝑙𝑖 , 𝑖] будет на стеке, когда мы положим 𝑖.
7. Коровы и стойла #2
Тот же бинпоиск, что и для обычных коров. Внутри бинпоиска нужно за 𝒪(𝑛) проверять,
что можно выбрать 𝑘 точек на окружности на расстоянии > 𝑚.
1. Отсортируем точки на окружности.
Удвоим массив: 𝑥[𝑖+𝑛] = 𝑥[𝑖] + 𝐿, где 𝐿 – длина окружности.
2. За 𝒪(𝑛) двумя указателями ∀𝑖 найдем 𝑛𝑒𝑥𝑡[𝑖] = min 𝑗 : 𝑥[𝑗] > 𝑥[𝑖] + 𝑚.
6/12
Алгоритмы, осень 2019/20
Практика #6. Сортировки, точки-экстремумы.
3. Теперь для любой точки можно за 𝑘−1 прыжок 𝑖 → 𝑛𝑒𝑥𝑡[𝑖] проверить, можно ли взять её
в ответ. Проверим точку 𝑥[0].
4.
• Не зациклились за 𝑘−1 прыжок ⇒ ок, расставили.
• Зациклились за < 𝑘−1 прыжков ⇒ ни с какой начать нельзя.
• Зациклились ровно за 𝑘−1 прыжок ⇒ окружность разбилась на 𝑘−1 часть, в одной
2𝑛
точек. Проверим каждую из них за 𝒪(𝑘).
из них 6 𝑘−1
Итого время работы 𝒪(𝑛 log 𝑀 ).
7/12
Алгоритмы, осень 2019/20
Практика #6. Сортировки, точки-экстремумы.
Домашнее задание
5.1. Обязательная часть
1. (3) Ближайшие к медиане
Дан массив A[1..n] из 𝑛 различных чисел. Массив не обязательно отсортирован. Требуется
найти 𝑘 ближайших к медиане элементов за линейное время. Решить для двух метрик.
a) (1) По позиции в отсортированном массиве.
𝑑(𝑥, median) = |pos(𝑥) − pos(median)|,
где pos(𝑥) — позиция элемента 𝑥 в отсортированном массиве.
b) (2) По значению.
𝑑(𝑥, median) = |𝑥 − median|.
2. (4) Поиск точки
a) (1)[︁ Даны 𝑛 точек
на прямой 𝑥𝑖 с весами 𝑤𝑖 > 0. Найти точку 𝑥* :
]︁
∑︀
𝑤𝑖 (𝑥𝑖 − 𝑥* )2 → min
𝑖
b) (1)[︁ Даны 𝑛 точек на плоскости
(𝑥𝑖 , 𝑦𝑖 ) с весами 𝑤𝑖 > 0. Найти точку (𝑥* , 𝑦 * ):
]︁
∑︀
𝑤𝑖 (|𝑥𝑖 − 𝑥* | + |𝑦𝑖 − 𝑦 * |) → min
𝑖
c) (2) Даны
𝑛 точек на плоскости
(𝑥𝑖 , 𝑦𝑖 ) с весами 𝑤𝑖 > 0. Найти точку (𝑥* , 𝑦 * ):
[︁
]︁
max 𝑤𝑖 (|𝑥𝑖 − 𝑥* | + |𝑦𝑖 − 𝑦 * |) → min.
𝑖
Дополнительный (+1) балл можно заработать, решив эту задачу 𝒪(sort + 𝑛).
3. (3) Поиск двух точек
На прямой расположено 𝑛 точек
𝑝1 , 𝑝2 , . . . , 𝑝𝑛 . Каждая]︁ точка имеет вес 𝑤𝑖 > 0.
∑︀[︁
Выбрать две точки 𝑞1 , 𝑞2 :
𝑤𝑖 · min(|𝑝𝑖 − 𝑞1 |, |𝑝𝑖 − 𝑞2 |) → min.
𝑖
Решение за 𝒪(𝑛2 ) даст один балл из трёх.
Hint: перебирать можно не только координаты 𝑞𝑖 .
4. (3) Поиск многих статистик
Дан массив из 𝑛 чисел и 𝑚 чисел 𝑝1 , 𝑝2 , . . . 𝑝𝑚 ,
нужно за 𝒪(𝑛 log 𝑚 + 𝑚) для каждого 𝑖 найти 𝑝𝑖 -ую порядковую статистику.
5. (2) Поиск статистики
Оцените сложность детерминированного алгоритма поиска 𝑘 статистики, если в нем разбивать на группы не по 5 элементов, а по:
a) (1) 7
b) (1) 3
8/12
Алгоритмы, осень 2019/20
Практика #6. Сортировки, точки-экстремумы.
5.2. Дополнительная часть
1. (2) Сортировка вещественных чисел
Даны 𝑛 вещественных чисел из [0, 1] в произвольном порядке. Представим, что они уже
отсортированы и посмотрим на разности соседних чисел. Нужно найти максимальную такую
разность за 𝒪(𝑛).
2. (3) Поиск центра
* *
Даны
[︁ 𝑛 точек на плоскости (𝑥]︁𝑖 , 𝑦𝑖 ) с весами 𝑤𝑖 > 0. Найти точку (𝑥 , 𝑦 ):
max 𝑤𝑖 ((𝑥𝑖 − 𝑥* )2 + (𝑦𝑖 − 𝑦 * )2 ) → min.
𝑖
Будут оценены решения за линию на полилогарифм.
3. (3) Поиск трех точек
На прямой расположено
𝑛 точек 𝑝1 , 𝑝2 , . . . , 𝑝𝑛 . Каждая
]︁ точка имеет вес 𝑤𝑖 > 0. Выбрать три
∑︀[︁
𝑤𝑖 · min(|𝑝𝑖 − 𝑞1 |, |𝑝𝑖 − 𝑞2 |, |𝑝𝑖 − 𝑞3 |) → min.
точки 𝑞1 , 𝑞2 , 𝑞3 :
𝑖
Требуется решение за линию на полилогарифм.
4. (2) Амортизированная вставка в кучу
Придумайте, как модифицировать обычную бинарную кучу так, чтобы Add работал за амортизированное 𝒪(log log 𝑛).
5. (5) Нижняя оценка на построение кучи
Внимание: эту задачу можно сдавать только до лекции.
Какое минимальное число сравнений нужно, чтобы построить обычную бинарную кучу?
Докажите максимально точную нижнюю оценку. Для простоты вычислений предположим,
что в массиве 𝑛 = 2𝑘 − 1 элементов.
a) (1) Хотя бы 𝑛 − 1 сравнений.
b) (1.5) Хотя бы 𝑛 сравнений для 𝑛 > 10.
c) (3) Оценка 1.3644 · 𝑛 + 𝒪(1) без строгого доказательства.
d) (5) Оценка 1.4999 · 𝑛 + 𝒪(1) без строгого доказательства.
9/12
Алгоритмы, осень 2019/20
Практика #6. Сортировки, точки-экстремумы.
Разбор домашнего задания
6.1. Обязательная часть
1. Ближайшие к медиане
a) По позиции: найти статистики номер 𝑙 = 𝑛2 − 𝑘2 и 𝑟 = 𝑛2 + 𝑘2 , взять числа между ними.
Поиск порядковой статистики заодно делает partition ⇒ отрезок [𝑙, 𝑟] массива станет
ответом.
b) По значению: ищем медиану 𝑥, строим массив 𝑏𝑖 = |𝑎𝑖 − 𝑥|. В массиве 𝑏 ищем 𝑘-ю
статистику, берем 𝑘 минимальных элементов 𝑏.
2. Поиск
∑︀[︁ точки * 2 ]︁
a)
𝑤𝑖 (𝑥𝑖 − 𝑥 ) → min
𝑖
∑︀
Дифференцируем. Получаем 𝑥* = ∑︀𝑥𝑤𝑖 𝑤𝑖 𝑖 .
]︁
]︁ ∑︀[︁
]︁ ∑︀[︁
∑︀[︁
*
*
*
*
𝑤𝑖 |𝑦𝑖 − 𝑦 |) → min
𝑤𝑖 |𝑥𝑖 − 𝑥 | +
𝑤𝑖 (|𝑥𝑖 − 𝑥 | + |𝑦𝑖 − 𝑦 |) =
b)
𝑖
𝑖
𝑖
Поиск 𝑥 и 𝑦 независимы. Одномерную задачу умеем решать за 𝒪(𝑛) (без сортировки) –
взвешенная
𝑘-я порядковая]︁статистика.
[︁
c) max 𝑤𝑖 (|𝑥𝑖 − 𝑥* | + |𝑦𝑖 − 𝑦 * |) → min.
𝑖
Решение #1: бинпоиск по ответу, внутри видим
ромбики разного размера,
пересекаем.
[︁
]︁
∘
*
*
Решение #2: повернём на 45 , получим max 𝑤𝑖 max(|𝑥𝑖 − 𝑥 |, |𝑦𝑖 − 𝑦 |) → min.
𝑖
Координаты независимы, решим одномерную задачу.
Можно бинпоиск по ответу. Проверка 𝑚: пересечем отрезки [𝑥𝑖 − 𝑤𝑚𝑖 , 𝑥𝑖 + 𝑤𝑚𝑖 ].
А можно заметить, что |𝑥𝑖 − 𝑥* | = max(𝑥𝑖 − 𝑥* , 𝑥* − 𝑥𝑖 )
⇒ нам нужно max𝑖 max(𝑤𝑖 (𝑥𝑖 − 𝑥* ), 𝑤𝑖 (𝑥* − 𝑥𝑖 )) → min.
Видим максимум 2𝑛 линейных функций, для его поиска ищем пересечение 2𝑛 полуплоскостей за 𝒪(sort+𝑛): сортируем прямые по углу, делаем проход со стеком (оно же convex
hull trick).
3. Поиск двух точек
Заметим, что в результате точки разобьются на «левую половину» и «правую половину» –
те, что ближе к 𝑞1 , и те, что ближе к 𝑞2 .
Отсортируем точки и применим метод∑︀
трёх указателей.
𝑚,
∑︀ Перебираем
∑︀ границу половинок
∑︀
внутри перебора двигаем 𝑞1 и 𝑞2 , пока 𝑖∈[0,𝑞1 ) 𝑤𝑖 6 𝑖∈[𝑞1 ,𝑚) 𝑤𝑖 и 𝑖∈[𝑚,𝑞2 ) 𝑤𝑖 6 𝑖∈[𝑞2 ,𝑛) 𝑤𝑖 .
Как пересчитывать ответ? При сдвиге 𝑚 прибавится 𝑤𝑚 ((𝑥𝑚 − 𝑥𝑞1 ) − (𝑥𝑞2 − 𝑥𝑚 )), при сдвиге
𝑞1 прибавится (𝑤1𝑙 − 𝑤1𝑟 )(𝑥𝑞1 +1 − 𝑥𝑞1 ).
Корректность. Пусть в ответе граница 𝑚. При переборе мы ее не пропустим, выставим 𝑞1
и 𝑞2 во взвешенные медианы.
Почему в коректном ответе 𝑞1 и 𝑞2 – взвешенные медианы? Пусть не так.
Если 𝑞1 не медиана, сдвинем ее в медиану. Тогда улучшили ответ при фиксированной границе.
Но при сдвиге 𝑞1 могла измениться настоящая граница. Сдвинем границу в настоящую. Ответ
снова улучшился: теперь некоторые точки переехали к более близкой из 𝑞1 и 𝑞2 .
10/12
Алгоритмы, осень 2019/20
Практика #6. Сортировки, точки-экстремумы.
4. Поиск многих статистик
Отсортируем подсчетом массив статистик за 𝒪(𝑚 + 𝑛).
Найдём статистику 𝑝𝑚/2 , пусть её позиция – 𝑖. Разобьём задачу на две – поиск статистик с
номерами [1.. 𝑚2 ) на отрезке массива [1..𝑖) и поиск ( 𝑚2 ..𝑚] на отрезке массива (𝑖..𝑛].
Глубина рекурсии log 𝑚, на каждом уровне рекурсии суммарная длина массивов не более 𝑛.
Итого 𝒪(𝑛 log 𝑚).
5. Поиск статистики
a) 7: 𝑇 (𝑛) = 𝑛 + 𝑇 ( 𝑛7 ) + 𝑇 (𝑛 −
b) 3: 𝑇 (𝑛) = 𝑛 + 𝑇 ( 𝑛3 ) + 𝑇 (𝑛 −
⌈7/2⌉𝑛
),
14
⌈3/2⌉𝑛
),
6
1
7
1
3
+
+
5
7
2
3
< 1 ⇒ Θ(𝑛).
= 1 ⇒ Θ(𝑛 log 𝑛).
6.2. Дополнительная часть
1. Сортировка вещественных чисел
. Проделаем одну итерацию модифицированПо принципу Дирихле, ответ не менее 𝑚𝑎𝑥−𝑚𝑖𝑛
𝑛−1
𝑚𝑎𝑥−𝑚𝑖𝑛
ного BucketSort, пусть длина одного bucket: 𝑛−1 .
Не сложно видеть, что ответ не может лежать внутри одного bucket (такой ответ слишком
маленький), только в разных, хотя и не обязательно соседних. Для каждого bucket найдём минимум и максимум в нём, обновим ответ разницей минимума bucket и максимума в
предыдущем непустом bucket.
2. Поиск центра[︁
]︁
𝑓 (𝑥* , 𝑦 * ) = max 𝑤𝑖 ((𝑥𝑖 − 𝑥* )2 + (𝑦𝑖 − 𝑦 * )2 ) → min.
𝑖
Два вложенных троичных поиска.
При фиксированом 𝑥 получаем 𝑔(𝑦) = 𝑓 (𝑥, 𝑦). 𝑔(𝑦) – максимум функций, каждая из которых
имеет один локальный минимум. Можно показать по индукции, что тогда 𝑔(𝑦) тоже имеет
один локальный минимум.
Значит, точку 𝑦 * , можно найти троичным поиском.
Так получили функцию 𝑦 * (𝑥). Определим ℎ(𝑥) = 𝑓 (𝑥, 𝑦 * (𝑥)).
Без док-ва: ℎ(𝑥) имеет один локальный минимум, который можно найти троичным поиском.
Итого 𝒪(𝑛 log2 𝑀 ), где 𝑀 – max координата.
Существует также вероятностное решение за 𝒪(𝑛).
3. Поиск трех точек
Умеем считать 𝑓2 [𝑖] – оптимальную цену выбора двух точек для отрезка [0..𝑖). Из нее можно
за 𝒪(𝑛 log 𝑛) получить искомую 𝑓3 [𝑖].
Пусть 𝑝𝑖 – оптимальная граница, делящая [0..𝑖) на две области: в первой две точки, во второй
одна (min из таких границ, если их несколько).
Если найти 𝑝𝑛 , то легко высчитать ответ.
Главное наблюдение: 𝑝𝑖 6 𝑝𝑖+1 .
Основная идея – метод «разделяй и властвуй».
Можно написать функцию count(𝑙, 𝑟, 𝐿, 𝑅), которая ищет 𝑝𝑖 для всех 𝑖 ∈ [𝑙, 𝑟], зная, что
𝐿 6 𝑝𝑖 6 𝑅 (используя 𝑝𝑖 6 𝑝𝑖+1 ).
count(𝑙, 𝑟, 𝐿, 𝑅) будет искать 𝑝(𝑙+𝑟)/2 перебором за 𝑅 − 𝐿 + 1 и рекурсивно делиться.
Более подробно будет в лекциях по динамике.
11/12
Алгоритмы, осень 2019/20
Практика #6. Сортировки, точки-экстремумы.
4. Амортизированная вставка в кучу
Add будет за 𝒪(1) добавлять элемент в неупорядоченный список «свежедобавленных».
Когда «свежедобавленных» стало 𝑘 = log 𝑛, надо переложить их в кучу.
Допишем их в конец кучи и рассмотрим объединение путей от них до корня.
Объединение путей состоит из верхушки-пути длины 𝒪(log 𝑛) и кучи из 𝒪(𝑘) элементов.
Сортируем эти 𝒪(𝑘 + log 𝑛) элементов и укладываем в нужном порядке.
Получилось как раз 𝒪(log 𝑛 log log 𝑛).
5. Нижняя оценка на построение кучи
1.3644 · 𝑛 будет на лекции.
1.4999 · 𝑛 можно получить, рассмотрев кучу из 𝑛 = 2𝑘 − 1 элементов и показав, что выбор
минимума в поддереве размера 2𝑖 − 1 придётся делать не за log(2𝑖 − 1), а за ⌈log(2𝑖 − 1)⌉ = 𝑖
сравнений.
12/12
Скачать