Это не совсем конкретное решение, просто идея. Как насчет построения quadtree по осям A и B? Вы бы пошли вниз по дереву, скажем, в ширину; тогда:
- всякий раз, когда вы найдете поддерево со значениями A, выходящими за пределы заданного диапазона [X, Y], вы отбрасываете это поддерево (и не повторяете);
- всякий раз, когда вы обнаруживаете поддерево с A-значениями внутри заданного диапазона [X, Y], вы добавляете это поддерево в набор S, который вы строите, и не рекурсивно;
- всякий раз, когда вы находите поддерево с некоторыми значениями A внутри диапазона [X, Y], а некоторые снаружи, вы возвращаетесь в него.
Теперь у вас есть множество S всех максимальных поддеревьев с A-координатами между X и Y; существует не более O (sqrt (m)) из этих поддеревьев, что я покажу ниже.
Некоторые из этих поддеревьев будут содержать записи O (m) (разумеется, они будут содержать все записи O (m), добавленные вместе), поэтому мы не можем ничего сделать со всеми записями всех поддеревьев. Теперь мы можем создать кучу поддеревьев в S, так что B-минимум каждого поддерева меньше, чем B-минимумы его дочерних элементов в куче. Теперь извлекаем B-минимальные элементы из верхнего узла кучи, пока у вас не будет N из них; всякий раз, когда вы извлекаете элемент из поддерева с k элементами, вам необходимо разложить это поддерево на O (log (k)) поддеревьев, не содержащих недавно извлеченный элемент.
Теперь давайте рассмотрим сложность. Поиск O (sqrt (m)) поддеревьев займет не более O (sqrt (m)) шагов (упражнение для читателя, используя аргументы в доказательстве ниже). Мы, вероятно, должны вставить их в кучу, когда мы их найдем; это займет O (sqrt (m) * log (sqrt (m))) = O (sqrt (m) * log (m)) шагов. Извлечение одного элемента из поддерева k-элемента в куче занимает O (sqrt (k)) время, чтобы найти элемент, а затем вставляет O (log (sqrt (k))) = O (log (k)) назад. в кучу размером O (sqrt (m)) требуется O (log (k) * log (sqrt (m))) = O (log (k) * log (m)) шагов. Вероятно, мы можем быть умнее, используя потенциалы, но мы можем, по крайней мере, связать k с m, так что получается N * (O (sqrt (k) + log (k) * log (m))) = O (N * (sqrt ( m) + log (m) ^ 2) = O (N * sqrt (m)) шагов для извлечения и O (sqrt (m) * (N + log (m))) всего шагов ... что составляет сублинейный в м.
Вот доказательство границы O (sqrt (m)) поддеревьев. Существует несколько стратегий построения квадродерева, но для простоты анализа, скажем, мы создаем двоичное дерево; в корневом узле мы разделяем набор данных в соответствии с A-координатой вокруг точки с медианной A-координатой, затем на один уровень вниз мы разделяем набор данных в соответствии с B-координатой вокруг точки с медианной B-координатой (то есть медиана для половины точек, содержащихся в этой половине дерева), и продолжайте чередовать направление на уровень.
Высота дерева - бревно (м). Теперь давайте рассмотрим, сколько поддеревьев нам нужно рекурсировать. Нам нужно выполнить рекурсию, только если поддерево содержит A-координату X или A-координату Y, или оба. На (2 * k) -ом уровне вниз, есть 2 ^ (2 * k) поддеревья в общей сложности. К тому времени каждое поддерево уже имеет свой A-диапазон, подразделяемый уже k раз, и каждый раз, когда мы делаем это, только половина деревьев содержит A-координату X. Таким образом, не более 2 ^ k поддеревьев содержат A-координату X. Аналогично, в самое большее 2 ^ k будет содержать A-координату Y. Это означает, что в общей сложности мы вернемся в самое большее 2 * сумма (2 ^ k, k = 0 .. log (m) / 2) = 2 * (2 ^ ( log (m) / 2 - 1) + 1) = O (sqrt (m)) поддеревьев.
Поскольку мы исследуем не более 2 ^ k поддеревьев на (2 * k) -ом уровне вниз, мы также можем добавить не более 2 ^ k поддеревьев на этом уровне в S. Это дает окончательный результат.