Пересечение прямоугольника с множеством непересекающихся отрезков (segment tree) — различия между версиями
(→Запрос) |
|||
Строка 1: | Строка 1: | ||
+ | {| class="wikitable" align="center" style="color: red; background-color: black; font-size: 56px; width: 800px;" | ||
+ | |+ | ||
+ | |-align="center" | ||
+ | |'''НЕТ ВОЙНЕ''' | ||
+ | |-style="font-size: 16px;" | ||
+ | | | ||
+ | 24 февраля 2022 года российское руководство во главе с Владимиром Путиным развязало агрессивную войну против Украины. В глазах всего мира это военное преступление совершено от лица всей страны, всех россиян. | ||
+ | |||
+ | Будучи гражданами Российской Федерации, мы против своей воли оказались ответственными за нарушение международного права, военное вторжение и массовую гибель людей. Чудовищность совершенного преступления не оставляет возможности промолчать или ограничиться пассивным несогласием. | ||
+ | |||
+ | Мы убеждены в абсолютной ценности человеческой жизни, в незыблемости прав и свобод личности. Режим Путина — угроза этим ценностям. Наша задача — обьединить все силы для сопротивления ей. | ||
+ | |||
+ | Эту войну начали не россияне, а обезумевший диктатор. И наш гражданский долг — сделать всё, чтобы её остановить. | ||
+ | |||
+ | ''Антивоенный комитет России'' | ||
+ | |-style="font-size: 16px;" | ||
+ | |Распространяйте правду о текущих событиях, оберегайте от пропаганды своих друзей и близких. Изменение общественного восприятия войны - ключ к её завершению. | ||
+ | |-style="font-size: 16px;" | ||
+ | |[https://meduza.io/ meduza.io], [https://www.youtube.com/c/popularpolitics/videos Популярная политика], [https://novayagazeta.ru/ Новая газета], [https://zona.media/ zona.media], [https://www.youtube.com/c/MackNack/videos Майкл Наки]. | ||
+ | |} | ||
+ | |||
== Задача == | == Задача == | ||
Есть множество непересекающихся отрезков в <tex>\mathbb{R}^2</tex>, нужно уметь отвечать на запросы, какие из них пересекают границу данного axis-aligned (стороны параллельны осям координат) прямоугольника. | Есть множество непересекающихся отрезков в <tex>\mathbb{R}^2</tex>, нужно уметь отвечать на запросы, какие из них пересекают границу данного axis-aligned (стороны параллельны осям координат) прямоугольника. |
Версия 08:30, 1 сентября 2022
НЕТ ВОЙНЕ |
24 февраля 2022 года российское руководство во главе с Владимиром Путиным развязало агрессивную войну против Украины. В глазах всего мира это военное преступление совершено от лица всей страны, всех россиян. Будучи гражданами Российской Федерации, мы против своей воли оказались ответственными за нарушение международного права, военное вторжение и массовую гибель людей. Чудовищность совершенного преступления не оставляет возможности промолчать или ограничиться пассивным несогласием. Мы убеждены в абсолютной ценности человеческой жизни, в незыблемости прав и свобод личности. Режим Путина — угроза этим ценностям. Наша задача — обьединить все силы для сопротивления ей. Эту войну начали не россияне, а обезумевший диктатор. И наш гражданский долг — сделать всё, чтобы её остановить. Антивоенный комитет России |
Распространяйте правду о текущих событиях, оберегайте от пропаганды своих друзей и близких. Изменение общественного восприятия войны - ключ к её завершению. |
meduza.io, Популярная политика, Новая газета, zona.media, Майкл Наки. |
Задача
Есть множество непересекающихся отрезков в
, нужно уметь отвечать на запросы, какие из них пересекают границу данного axis-aligned (стороны параллельны осям координат) прямоугольника.Дерево отрезков
Для решения задачи потребуется структура данных, которая называется дерево отрезков (segment tree). NB: по-русски этими словами принято обозначать несколько другую структуру данных, здесь не о ней.
Пусть
— множество отрезков на вещественной оси. Возьмем концы этих отрезков и отсортируем их, получим точки . Назовем множеством элементарных интервалов .Построим сбалансированное бинарное дерево, листам которого будут соответствовать элементарные интервалы, а внутренним вершинам — объединения интервалов в потомках. Будем обозначать интервал, соответствующий вершине
, . В каждой вершине будем хранить соответствующий ей интервал и множество отрезков , таких что и . По-человечески это значит, что интервал вершины должен полностью лежать внутри отрезка и для родителя вершины это не так. По картинке должно быть понятно.Лемма (Оценка на память): |
Дерево отрезков занимает памяти. |
Доказательство: |
Всего элементарных интервалов не больше (в случае, когда все отрезки не пересекаются: для каждого отрезок левее , , , и еще один ). Так как дерево сбалансированное, его глубина .Утверждается, что один отрезок на одной глубине встречается не более двух раз. Пусть это не так, возьмем три упорядоченные вершины , содержащие этот отрезок. Очевидно, что сосед тоже содержит этот отрезок (см. картинку). Тогда этот отрезок должен содержаться в . Противоречие. Глубина , всего отрезков , на каждом уровне отрезок встречается раз — победа. |
Построение дерева
Сначала сортируем концы отрезков из
за . За собираем сбалансированное дерево (просто поднимаясь от листьев к корню и объединяя интервалы). Осталось найти для вершин дерева. Для этого вставим туда каждый отрезок по такому алгоритму:def InsertSegment(v, [x : x']): if: v.Add([x : x']) else: if : InsertSegment(v.Left, [x : x']) if : InsertSegment(v.Right, [x : x'])
Это работает за
, потому что на каждом уровне есть не более двух вершин, в которые отрезок нужно вставить и еще не более двух вершин, содержащих его концы. Таким образом, на каждом уровне нужно обработать не более четырех вершин. Итого для всех отрезков получаем .Запрос
Теперь научимся отвечать на запрос, какие отрезки содержат заданную точку.
def Query(v, p, S): S = SI(v) if !v.IsLeaf: if : Query(v.Left, p, S) else Query(v.Right, p, S) Query(root, p, )
Запрос работает за
, где — размер ответа.Алгоритм
Чтобы решить исходную задачу, нужно уметь находить, какие отрезки из
пересекают axis-aligned отрезок . Рассмотрим случай, когда параллелен оси , для все делается аналогично.В дереве отрезков будем хранить их проекции на ось
. Это позволит найти, какие отрезки пересекают бесконечную вертикальную линию. Осталось найти, какие из них пересекают заданный отрезок.Используем то, что отрезки не пересекаются, и
: это значит, что отрезки внутри элементарного интервала могут быть вертикально упорядочены. В вместо списка теперь будем хранить дерево поиска.При запросе будем выдавать только те отрезки, для которых верхняя граница запроса выше точки пересечения с вертикальной линией, а нижняя — ниже (то есть все, что находится между lower_bound и upper_bound в дереве, проверяем выше/ниже поворотом).
Таким образом, обработка одной вершины занимает
времени, где — количество отрезков в ответе, полученных из вершины , всего посещенных вершин , итого . Препроцессинг выполняется за из-за вставки в дерево поиска.Ссылки
- Английская википедия
- de Berg, van Kreveld, Overmars, Schwarzkopf "Computational Geometry Algorithms and Applications", p. 231