algorithm-dev

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub today2098/algorithm-dev

:question: Longest Increasing Subsequence(最長増加部分列)
(algorithm/Others/longest_increasing_subsequence.hpp)

概要

長さ $N$ の数列 $\lbrace a_0, a_1, \ldots, a_{N-1} \rbrace$ に対して,最長増加部分列 (LIS: Longest Increasing Subsequence) の長さを求める.

アルゴリズムの計算量は $\mathcal{O}(N \log N)$ となる.

参考文献

  1. 秋葉 拓哉, 岩田 陽一, 北川 宜稔. “2-3 値を覚えて再利用 ‘動的計画法’”. プログラミングコンテストチャレンジブック. 第2版, マイナビ出版, 2012, p.63-65.

問題

  1. “F - Useless for LIS”. AtCoder Beginner Contest 354. AtCoder. https://atcoder.jp/contests/abc354/tasks/abc354_f.

Verified with

Code

#ifndef ALGORITHM_LONGEST_INCREASING_SUBSEQUENCE_HPP
#define ALGORITHM_LONGEST_INCREASING_SUBSEQUENCE_HPP 1

/**
 * @brief Longest Increasing Subsequence(最長増加部分列)
 * @docs docs/Others/longest_increasing_subsequence.md
 */

#include <algorithm>
#include <functional>
#include <vector>

namespace algorithm {

// 最長増加部分列 (LIS: Longest Increasing Subsequence) の長さを求める.O(N*logN).
template <typename Type, class Compare = std::function<bool(const Type &, const Type &)> >
std::vector<int> lis(const std::vector<Type> &v, Compare comp = [](const Type &a, const Type &b) -> bool { return a < b; }) {
    const int n = v.size();
    std::vector<int> res(n, 0);  // res[i]:=(v[i]を最後の要素とする最長増加部分列の長さ).
    std::vector<Type> dp;        // dp[k]:=(長さkの増加部分列のうち,その最後の要素の最小値).
    for(int i = 0; i < n; ++i) {
        auto itr = std::lower_bound(dp.begin(), dp.end(), v[i], comp);
        res[i] = itr - dp.begin() + 1;
        if(itr == dp.end()) dp.push_back(v[i]);
        else *itr = v[i];
    }
    return res;
}

// 最長増加部分列 (LIS: Longest Increasing Subsequence) の長さを求める.O(N*logN).
template <typename Type, class Compare = std::function<bool(const Type &, const Type &)> >
std::vector<int> lis2(const std::vector<Type> &v, Compare comp = [](const Type &a, const Type &b) -> bool { return a < b; }) {
    const int n = v.size();
    std::vector<int> res(n + 1, 0);  // res[i]:=(v[:i]における最長増加部分列の長さ).
    std::vector<Type> dp;            // dp[k]:=(長さkの増加部分列のうち,その最後の要素の最小値).
    for(int i = 0; i < n; ++i) {
        auto itr = std::lower_bound(dp.begin(), dp.end(), v[i], comp);
        if(itr == dp.end()) dp.push_back(v[i]);
        else *itr = v[i];
        res[i + 1] = dp.size();
    }
    return res;
}

}  // namespace algorithm

#endif
#line 1 "algorithm/Others/longest_increasing_subsequence.hpp"



/**
 * @brief Longest Increasing Subsequence(最長増加部分列)
 * @docs docs/Others/longest_increasing_subsequence.md
 */

#include <algorithm>
#include <functional>
#include <vector>

namespace algorithm {

// 最長増加部分列 (LIS: Longest Increasing Subsequence) の長さを求める.O(N*logN).
template <typename Type, class Compare = std::function<bool(const Type &, const Type &)> >
std::vector<int> lis(const std::vector<Type> &v, Compare comp = [](const Type &a, const Type &b) -> bool { return a < b; }) {
    const int n = v.size();
    std::vector<int> res(n, 0);  // res[i]:=(v[i]を最後の要素とする最長増加部分列の長さ).
    std::vector<Type> dp;        // dp[k]:=(長さkの増加部分列のうち,その最後の要素の最小値).
    for(int i = 0; i < n; ++i) {
        auto itr = std::lower_bound(dp.begin(), dp.end(), v[i], comp);
        res[i] = itr - dp.begin() + 1;
        if(itr == dp.end()) dp.push_back(v[i]);
        else *itr = v[i];
    }
    return res;
}

// 最長増加部分列 (LIS: Longest Increasing Subsequence) の長さを求める.O(N*logN).
template <typename Type, class Compare = std::function<bool(const Type &, const Type &)> >
std::vector<int> lis2(const std::vector<Type> &v, Compare comp = [](const Type &a, const Type &b) -> bool { return a < b; }) {
    const int n = v.size();
    std::vector<int> res(n + 1, 0);  // res[i]:=(v[:i]における最長増加部分列の長さ).
    std::vector<Type> dp;            // dp[k]:=(長さkの増加部分列のうち,その最後の要素の最小値).
    for(int i = 0; i < n; ++i) {
        auto itr = std::lower_bound(dp.begin(), dp.end(), v[i], comp);
        if(itr == dp.end()) dp.push_back(v[i]);
        else *itr = v[i];
        res[i + 1] = dp.size();
    }
    return res;
}

}  // namespace algorithm
Back to top page