15.4. Наибольшая возрастающая подпоследовательность
Определение
Наибольшая возрастающая подпоследовательность (НВП, longest increasing subsequence, LIS) последовательности $a_1, \ldots, a_n$ — это подпоследовательность максимальной длины, в которой каждое следующее число строго больше предыдущего.
Дана последовательность чисел $a_{1}, \ldots, a_{n}$. Требуется найти возрастающую подпоследовательность максимально возможной длины.
Решение за $O(n^2)$
Пусть $l_i$ — максимально возможная длина возрастающей подпоследовательности, заканчивающейся в $a_i$. Тогда
$$ l_{i} = 1 + \max_{\substack{0 \leqslant j < i,\\ a_{j} < a_{i}}} l_{j} $$(максимум по пустому множеству считаем равным нулю). Ответ на задачу — максимальное значение $l_i$ по всем $i$. Восстановление ответа делается стандартными методами. Получаем решение за $O(n^2)$.
Решение за $O(n \log n)$
Будем поддерживать дополнительный массив: пусть
$$ x[k] = \min_{\substack{j \leqslant i,\\ l_j = k}} a_j $$(минимум по пустому множеству — бесконечность). Тогда $l_i = 1 + \max_{k:\, x[k] < a_i} k$.
Теорема
Элементы массива $x[i]$ идут в строгом порядке возрастания: для любого $k > 1$ выполняется $x[k-1] < x[k]$.
Поскольку элементы массива $x$ идут в порядке возрастания, $l_i$ можно найти двоичным поиском за $O(\log n)$. При переходе от $i$ к $i+1$ массив $x$ меняется не более чем в одной ячейке: $x[l_i] = \min(x[l_i], a_i)$.
Восстановление ответа
Для восстановления вместе с массивом $x$ будем поддерживать массив списков pos: в момент присвоения $x[l_i] = a_i$ допишем $i$ в конец списка $\operatorname{pos}[l_i]$. Чтобы найти предыдущий элемент в НВП, заканчивающейся в позиции $i$, нужно найти максимальный элемент в $\operatorname{pos}[l_i - 1]$, меньший $i$.