Пусть Предположим, что у нас есть структура данных, которая эффективно поддерживает следующие операции:
Добавить сегмент.
Удалить сегмент.
Возврат максимального количества сегментов, которые покрывают одну точку (то есть «лучшую» точку).
Если есть такая структура, мы можем получить эффективно использовать исходную задачу следующим образом:
Давайте создадим массив событий (одно событие для начала каждого сегмента и один для конца) и сортировать по координате x.
Добавить все сегменты в магическую структуру данных.
Итерируйте по всем событиям и выполните следующие действия: при начале сегмента добавьте его к числу сегментов, охватываемых в данный момент, и удалите их из этой структуры данных. Когда сегмент заканчивается, вычтите его из числа текущего охваченного сегмента и добавьте этот сегмент в магическую структуру данных. После каждого события обновите ответ на значение количества сегментов, охваченных в данный момент (он показывает, сколько сегментов покрывается точкой, которая соответствует текущему событию) плюс максимум, возвращаемый структурой данных, описанной выше (это показывает, как мы может выбрать другой пункт наилучшим образом).
Если эта структура данных могут выполнять все указанные операции в O(log n)
, то есть O(n log n)
решения (мы сортируем событие и сделать один проход над отсортированным массивом делает постоянное число запросов к этой структуре данных для каждого мероприятие).
Итак, как мы можем реализовать эту структуру данных? Ну, здесь отлично работает сегментное дерево. Добавление сегмента добавляет один к определенному диапазону. Удаление сегмента вычитает один из всех элементов в определенном диапазоне. Получить ting максимум - это стандартная максимальная операция на дереве сегментов. Поэтому нам нужно дерево сегментов, которое поддерживает две операции: добавьте константу в диапазон и получите максимум для всего дерева. Это можно сделать в O(log n)
времени на запрос.
Еще одно примечание: стандартное дерево сегментов требует, чтобы координаты были маленькими. Мы можем предположить, что они никогда не превышают 2 * n
(если это не так, мы можем их сжать).
'ровно две линии, перпендикулярной к them'? поэтому эти две линии будут параллельны оси y, нужно ли пересекать ось x в целочисленной точке? –
@PhamTrung, да, он должен быть либо крест, либо тронут. – inquisitive
В ** целочисленном ** пункте? или любой точки? –