This documentation is automatically generated by online-judge-tools/verification-helper
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/courses/library/7/DPL/1/DPL_1_D"
#include <iostream>
#include <vector>
#include "../algorithm/Others/longest_increasing_subsequence.hpp"
int main() {
int n;
std::cin >> n;
std::vector<int> a(n);
for(auto &in : a) std::cin >> in;
auto ans = algorithm::lis2(a).back();
std::cout << ans << std::endl;
}
#line 1 "verify/aoj-DPL_1_D-longest_increasing_subsequence.test.cpp"
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/courses/library/7/DPL/1/DPL_1_D"
#include <iostream>
#include <vector>
#line 1 "algorithm/Others/longest_increasing_subsequence.hpp"
/**
* @brief Longest Increasing Subsequence(最長増加部分列)
* @docs docs/Others/longest_increasing_subsequence.md
*/
#include <algorithm>
#include <functional>
#line 12 "algorithm/Others/longest_increasing_subsequence.hpp"
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
#line 7 "verify/aoj-DPL_1_D-longest_increasing_subsequence.test.cpp"
int main() {
int n;
std::cin >> n;
std::vector<int> a(n);
for(auto &in : a) std::cin >> in;
auto ans = algorithm::lis2(a).back();
std::cout << ans << std::endl;
}