ホーム > libalgo

最長増加部分列

概要

${a_i}$ から順番を変えずにいくつかの要素を取り除いた列 ${b_i}$ であって $i < j$ なら $b_i < b_j$ (または $b_i \leq b_j$) をみたすもののうち,長さが最大のものを最長増加部分列 (Longest Increasing Subsequence; LIS) という.

計算量

$O(N\log N)$

実装

template <class Array>
Array lis(const Array &x) {
    size_t n = x.size();
    const int INF = std::numeric_limits<decltype(x[0])>::max();
    Array dp(n, INF);
    for (size_t i = 0; i < n; i++) {
        *std::upper_bound(dp.begin(), dp.begin() + n, x[i]) = x[i];  // a_i <= a_j
        // *lower_bound(dp.begin(), dp.begin() + n, x[i]) = x[i]; // a_i < a_j
    }
    return Array(dp.begin(), std::lower_bound(dp.begin(), dp.begin() + n, INF));
}

検証

たくさん

参考文系

蟻本