Да, это можно сделать за O(log n), даже если вам придется отвечать на запросы онлайн. Однако для этого требуются довольно сложные приемы.
Сначала решим следующую задачу: по заданному массиву ответим на запросы вида «сколько чисел ‹= x содержится в индексах [l, r]». Это делается с помощью структуры, похожей на дерево сегментов, которую иногда называют деревом сортировки слиянием. По сути, это дерево сегментов, в котором каждый узел хранит отсортированный подмассив. Эта структура требует O(n log n) памяти (поскольку существует log n слоев, и каждый из них требует хранения n чисел). Он также построен на O(n log n): вы просто идете снизу вверх и для каждой внутренней вершины объединяете отсортированные списки ее дочерних элементов.
Вот пример. Скажем, 1 5 2 6 8 4 7 1
будет исходным массивом.
|1 1 2 4 5 6 7 8|
|1 2 5 6|1 4 7 8|
|1 5|2 6|4 8|1 7|
|1|5|2|6|8|4|7|1|
Теперь вы можете ответить на эти запросы за время O(log^2 n): просто сделайте регулярный запрос к дереву сегментов (обходя O(log n) узлов) и выполните бинарный поиск, чтобы узнать, сколько чисел ‹= x существует. в этом узле (дополнительно O (log n) отсюда).
Это можно ускорить до O(log n) с помощью дробного каскадирования, который в основном позволяет вам делать бинарный поиск не в каждом узле, а только в корне. Однако это достаточно сложно, чтобы описать его в посте.
Теперь вернемся к исходной задаче. Предположим, у вас есть массив a_1,..., a_n. Создайте еще один массив b_1, ..., b_n, где b_i = индекс следующего вхождения a_i в массиве или ∞, если это последнее вхождение.
Пример (1-индексированный):
a = 1 3 1 2 2 1 4 1
b = 3 ∞ 6 5 ∞ 8 ∞ ∞
Теперь посчитаем числа в [l, r]. Для каждого уникального числа мы посчитаем его последнее появление в сегменте. С понятием b_i вы можете видеть, что вхождение числа является последним тогда и только тогда, когда b_i > r
. Таким образом, проблема сводится к тому, «сколько чисел > r в отрезке [l, r]», что тривиально сводится к тому, что я описал выше.
Надеюсь, поможет.
person
Ivan Smirnov
schedule
30.09.2016
O(n)
является нижней границей, так как вам нужно смотреть на каждый элемент. - person sascha   schedule 30.09.2016O(r-l)
. - person sascha   schedule 30.09.2016