mathpath, особое спасибо за термины (антицепь и другие). Не совсем понятно, как дерево диапазонов (range tree) можно прикрутить к этой задаче. Оно же специально заточено под построение полного списка элементов, попадающих в указанный диапазон. Я так же из быстрого знакомства не понял, как оно работает в многомерном случае. Подскажите, пожалуйста, какую-нибудь литературу доходчивую почитать по этому поводу?
Есть набор точек на плоскости с координатами (x, y).
Ваша задача — найти все точки, у которых x находится в интервале [x1, x2], а y — в интервале [y1, y2].
Главная идея: Свести многомерную задачу к последовательности одномерных.
Первый уровень (по x): Сначала мы быстро находим все точки, которые подходят по координате x.
Второй уровень (по y): Внутри каждого кандидата из первого шага мы быстро проверяем, подходит ли он по координате y.
Конструктивно это реализуется следующим образом:
Основное дерево (по x):
Мы строим сбалансированное двоичное дерево поиска, ключом в котором является координата x точек.
Каждый узел этого дерева хранит не только точку (или ссылку), но и всё поддерево точек, отсортированных по y
Корень дерева содержит все точки, отсортированные по y.
Левый потомок корня содержит все точки из левого поддерева (те, у которых x меньше медианного), также отсортированные по y.
Правый потомок корня содержит все точки из правого поддерева, отсортированные по y.
Ассоциированная структура: Эта "внутренняя" структура (массив или еще одно дерево поиска, отсортированное по y) и есть ключ к эффективности.
Алгоритм поиска в таком дереве выглядит так:
Найти "узел-разделитель" (Split Node):
Мы спускаемся по основному дереву (по x), используя границы интервала [x1, x2], чтобы найти узел, где пути к x1 и x2 расходятся. Это корень поддерева, которое гарантированно содержит все точки с x в нужном диапазоне.
Рекурсивный обход:
От узла-разделителя мы идем влево по пути к x1.
Каждый раз, когда мы сворачиваем направо (т.е. текущий узел имеет x > x1, и мы идем в левое поддерево), это означает, что правое поддерево текущего узла целиком попадает в интервал по x.
Мы берем ассоциированную структуру этого правого поддерева (отсортированный список по y) и выполняем в ней бинарный поиск по интервалу [y1, y2], добавляя все найденные точки в результат.
Симметрично мы идем от узла-разделителя вправо по пути к x2.
Каждый раз, когда мы сворачиваем налево, его левое поддерево целиком попадает в интервал, и мы обрабатываем его ассоциированную структуру.
Вместо того чтобы проверять каждую точку, мы получаем O(log n) кандидатов (поддеревьев, полностью попадающих в диапазон по x).
В каждом таком кандидате мы тратим O(log n) на бинарный поиск по y.
Итоговая сложность: O(log² n + k), где k — число найденных точек .
-- 24.02.2026, 12:20 --Литература:
"2D Range Tree Demo" (Университет Мэриленда)
GitHub - CS558/extra-lecture-range-trees
"Foundations of Multidimensional and Metric Data Structures" Ханан Самет (Hanan Samet)
"An implementation of a multidimensional dynamic range tree based on an AVL tree" (Университет Нью-Брансуика)