Решаю задачу из Открытой олимпиады 2014-2015 года, если кому интересно, вот условие и разбор, задача последняя и в условиях, и в разборе. Путем некоторых хитрых преобразований задача была сведена к следующей, если я правильно понял: дана координатная плоскость, и какие-то координаты на одной оси, и какие-то координаты на другой. На пересечении всех этих координат находятся наши точки. Далее дано несколько прямоугольников, и надо найти точку, накрытую наибольшим числом прямоугольников. Решение с двумерным деревом отрезков/Фенвика довольно очевидно, но есть более быстрое решение с одномерным деревом и сканирующей прямой. В сканирующей прямой я пока разбираюсь слабо, поэтому не очень понимаю, как это именно реализовывать. Буду благодарен за помощь. :)
Давайте возьмем y-координаты всех точек, для которых нужно определить количество прямоугольников, покрывающих их, и отметим их на вертикальной прямой, находящейся в x = - ∞. Давайте теперь начнем непрерывно двигать эту прямую до x = + ∞ и поддерживать для каждой точки количество прямоугольников, покрывающих ее.
Собственно, вопрос: а в какие моменты данные количества будут изменяться? Ответ: когда наша прямая "входит" в прямоугольник (то есть, проходит через координату x = xleft и когда она "выходит" из него (проходит через координату x = xright). Ну, собственно говоря, мы можем построить отсортированный массив т.н. "событий", где события — это вход в прямоугольник, выход из прямоугольника и ответ на запрос количества покрывающих точку прямоугольников. Соответственно, для события входа в прямоугольник мы прибавляем единичку на отрезке [ybottom; ytop], для события выхода из прямоугольника — отнимаем единичку на соответствующем отрезке, а для события ответа на запрос — сохраняем значение количества покрывающих точку прямоугольников.
Одна маленькая тонкость: нужно понять, как правильно сортировать события с одинаковой x-координатой, но это оставлю в качестве упражнения для Вас.
Спасибо, всё кратко и понятно.