結果
問題 | No.992 最長増加部分列の数え上げ |
ユーザー |
|
提出日時 | 2024-11-09 22:32:55 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 154 ms / 2,000 ms |
コード長 | 35,746 bytes |
コンパイル時間 | 2,609 ms |
コンパイル使用メモリ | 208,220 KB |
最終ジャッジ日時 | 2025-02-25 03:24:28 |
ジャッジサーバーID (参考情報) |
judge3 / judge1 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 42 |
ソースコード
#line 1 "/home/anqooqie/.proconlib/tools/util.hpp"// To see the details of my library, visit my GitHub Pages.// https://anqooqie.github.io/proconlib/#ifdef LOCAL#ifndef _GLIBCXX_DEBUG#define _GLIBCXX_DEBUG#endif#else#ifndef NDEBUG#define NDEBUG#endif#endif#include <bits/stdc++.h>#line 1 "/home/anqooqie/.proconlib/tools/resize.hpp"#line 8 "/home/anqooqie/.proconlib/tools/resize.hpp"namespace tools {template <class T, class Allocator, typename Head>void resize(::std::vector<T, Allocator>& vector, const Head& head) {vector.resize(head);}template <class T, ::std::size_t N, typename Head>void resize([[maybe_unused]] ::std::array<T, N>& array, [[maybe_unused]] const Head& head) {assert(array.size() == static_cast<::std::size_t>(head));}template <class T, class Allocator, typename Head, typename... Tail>void resize(::std::vector<T, Allocator>& vector, const Head& head, const Tail&... tail);template <class T, ::std::size_t N, typename Head, typename... Tail>void resize(::std::array<T, N>& array, const Head& head, const Tail&... tail);template <class T, class Allocator, typename Head, typename... Tail>void resize(::std::vector<T, Allocator>& vector, const Head& head, const Tail&... tail) {vector.resize(head);for (auto& child : vector) {::tools::resize(child, tail...);}}template <class T, ::std::size_t N, typename Head, typename... Tail>void resize(::std::array<T, N>& array, [[maybe_unused]] const Head& head, const Tail&... tail) {assert(array.size() == static_cast<::std::size_t>(head));for (auto& child : array) {::tools::resize(child, tail...);}}}#line 1 "/home/anqooqie/.proconlib/tools/fill.hpp"#include <type_traits>#line 1 "/home/anqooqie/.proconlib/tools/is_range.hpp"#line 7 "/home/anqooqie/.proconlib/tools/is_range.hpp"namespace tools {template <typename T, typename = ::std::void_t<>>struct is_range : ::std::false_type {};template <typename T>struct is_range<T, ::std::void_t<decltype(::std::begin(::std::declval<T>()), ::std::end(::std::declval<T>()))>> : ::std::true_type {};template <typename T>inline constexpr bool is_range_v = ::tools::is_range<T>::value;}#line 11 "/home/anqooqie/.proconlib/tools/fill.hpp"namespace tools {template <class T, class Allocator, typename V>::std::enable_if_t<!::tools::is_range_v<T>, void> fill(::std::vector<T, Allocator>& vector, const V& value) {::std::fill(::std::begin(vector), ::std::end(vector), value);}template <class T, ::std::size_t N, typename V>::std::enable_if_t<!::tools::is_range_v<T>, void> fill(::std::array<T, N>& array, const V& value) {::std::fill(::std::begin(array), ::std::end(array), value);}template <class T, class Allocator, typename V>::std::enable_if_t<::tools::is_range_v<T>, void> fill(::std::vector<T, Allocator>& vector, const V& value);template <class T, ::std::size_t N, typename V>::std::enable_if_t<::tools::is_range_v<T>, void> fill(::std::array<T, N>& array, const V& value);template <class T, class Allocator, typename V>::std::enable_if_t<::tools::is_range_v<T>, void> fill(::std::vector<T, Allocator>& vector, const V& value) {for (auto& child : vector) {::tools::fill(child, value);}}template <class T, ::std::size_t N, typename V>::std::enable_if_t<::tools::is_range_v<T>, void> fill(::std::array<T, N>& array, const V& value) {for (auto& child : array) {::tools::fill(child, value);}}}#line 1 "/home/anqooqie/.proconlib/tools/extend_input.hpp"// WARNING:// This file adds functions to std namespace for convenience.// Strictly speaking, it is not allowed in C++.// It makes the program ill-formed to include this file, and may cause undefined behavior.#line 1 "/home/anqooqie/.proconlib/tools/has_mod.hpp"#line 6 "/home/anqooqie/.proconlib/tools/has_mod.hpp"namespace tools {template <typename T, typename = ::std::void_t<>>struct has_mod : ::std::false_type {};template <typename T>struct has_mod<T, ::std::void_t<decltype(::std::declval<T>().mod())>> : ::std::true_type {};template <typename T>inline constexpr bool has_mod_v = ::tools::has_mod<T>::value;}#line 16 "/home/anqooqie/.proconlib/tools/extend_input.hpp"namespace tools {namespace detail {namespace extend_input {template <typename T>::std::istream& read(::std::istream& is, T& container) {for (auto& v : container) {is >> v;}return is;}}}}namespace std {template <class T, ::std::size_t N>::std::istream& operator>>(::std::istream& is, ::std::array<T, N>& array) {return ::tools::detail::extend_input::read(is, array);}template <class T1, class T2>::std::istream& operator>>(::std::istream& is, ::std::pair<T1, T2>& pair) {return is >> pair.first >> pair.second;}template <int I = 0, typename... Args>::std::istream& operator>>(::std::istream& is, ::std::tuple<Args...>& tuple) {if constexpr (I < int(sizeof...(Args))) {is >> ::std::get<I>(tuple);return operator>><I + 1>(is, tuple);} else {return is;}}template <class T, class Allocator>::std::istream& operator>>(::std::istream& is, ::std::vector<T, Allocator>& vector) {return ::tools::detail::extend_input::read(is, vector);}template <typename T>::std::enable_if_t<::tools::has_mod_v<T>, ::std::istream&> operator>>(::std::istream& is, T& x) {long long n;is >> n;x = T(n);return is;}}#line 1 "/home/anqooqie/.proconlib/tools/extend_output.hpp"// WARNING:// This file adds functions to std namespace for convenience.// Strictly speaking, it is not allowed in C++.// It makes the program ill-formed to include this file, and may cause undefined behavior.#line 12 "/home/anqooqie/.proconlib/tools/extend_output.hpp"#include <optional>#line 24 "/home/anqooqie/.proconlib/tools/extend_output.hpp"namespace tools {namespace detail {namespace extend_output {template <typename T>::std::ostream& debug_print(::std::ostream& os, const T& container) {::std::string delimiter = "";os << '[';for (const auto& v : container) {os << delimiter << v;delimiter = ", ";}os << ']';return os;}}}}namespace std {template <class T, ::std::size_t N>::std::ostream& operator<<(::std::ostream& os, const ::std::array<T, N>& array) {return ::tools::detail::extend_output::debug_print(os, array);}template <class Key, class T, class Compare, class Allocator>::std::ostream& operator<<(::std::ostream& os, const ::std::map<Key, T, Compare, Allocator>& map) {return ::tools::detail::extend_output::debug_print(os, map);}template <typename T>::std::ostream& operator<<(::std::ostream& os, const ::std::optional<T>& optional) {if (optional) {return os << *optional;} else {return os << "null";}}template <class T1, class T2>::std::ostream& operator<<(::std::ostream& os, const ::std::pair<T1, T2>& pair) {return os << '[' << pair.first << ", " << pair.second << ']';}template <class T, class Container>::std::ostream& operator<<(::std::ostream& os, ::std::queue<T, Container>& queue) {::std::queue<T, Container> other = queue;::std::string delimiter = "";os << '[';while (!queue.empty()) {os << delimiter << queue.front();delimiter = ", ";queue.pop();}os << ']';queue = ::std::move(other);return os;}template <class Key, class Compare, class Allocator>::std::ostream& operator<<(::std::ostream& os, const ::std::set<Key, Compare, Allocator>& set) {return ::tools::detail::extend_output::debug_print(os, set);}template <class T, class Container>::std::ostream& operator<<(::std::ostream& os, ::std::stack<T, Container>& stack) {::std::stack<T, Container> other;while (!stack.empty()) {other.push(stack.top());stack.pop();}::std::string delimiter = "";os << '[';while (!other.empty()) {os << delimiter << other.top();delimiter = ", ";stack.push(other.top());other.pop();}os << ']';return os;}template <int I = -1, typename... Args>::std::ostream& operator<<(::std::ostream& os, const ::std::tuple<Args...>& tuple) {if constexpr (I == -1) {os << '[';} else if constexpr (I == int(sizeof...(Args))) {os << ']';} else if constexpr (I == 0) {os << ::std::get<I>(tuple);} else {os << ", " << ::std::get<I>(tuple);}if constexpr (I < int(sizeof...(Args))) {return operator<<<I + 1>(os, tuple);} else {return os;}}template <class Key, class T, class Hash, class Pred, class Allocator>::std::ostream& operator<<(::std::ostream& os, const ::std::unordered_map<Key, T, Hash, Pred, Allocator>& unordered_map) {return ::tools::detail::extend_output::debug_print(os, unordered_map);}template <class Key, class Hash, class Pred, class Allocator>::std::ostream& operator<<(::std::ostream& os, const ::std::unordered_set<Key, Hash, Pred, Allocator>& unordered_set) {return ::tools::detail::extend_output::debug_print(os, unordered_set);}template <class T, class Allocator>::std::ostream& operator<<(::std::ostream& os, const ::std::vector<T, Allocator>& vector) {return ::tools::detail::extend_output::debug_print(os, vector);}template <typename T>::std::enable_if_t<::tools::has_mod_v<T>, ::std::ostream&> operator<<(::std::ostream& os, const T& x) {return os << x.val();}}#line 1 "/home/anqooqie/.proconlib/tools/extend_hash.hpp"// WARNING:// This file adds partial specializations for classes in std namespace, for convenience.// Strictly speaking, it is not allowed in C++.// It makes the program ill-formed to include this file, and may cause undefined behavior.#line 1 "/home/anqooqie/.proconlib/tools/tuple_hash.hpp"#line 1 "/home/anqooqie/.proconlib/tools/now.hpp"#line 5 "/home/anqooqie/.proconlib/tools/now.hpp"namespace tools {inline long long now() {return ::std::chrono::duration_cast<::std::chrono::nanoseconds>(::std::chrono::high_resolution_clock::now().time_since_epoch()).count();}}#line 1 "/home/anqooqie/.proconlib/tools/hash_combine.hpp"#line 6 "/home/anqooqie/.proconlib/tools/hash_combine.hpp"// Source: https://github.com/google/cityhash/blob/f5dc54147fcce12cefd16548c8e760d68ac04226/src/city.h// License: MIT// Author: Google Inc.// Copyright (c) 2011 Google, Inc.//// Permission is hereby granted, free of charge, to any person obtaining a copy// of this software and associated documentation files (the "Software"), to deal// in the Software without restriction, including without limitation the rights// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell// copies of the Software, and to permit persons to whom the Software is// furnished to do so, subject to the following conditions://// The above copyright notice and this permission notice shall be included in// all copies or substantial portions of the Software.//// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN// THE SOFTWARE.namespace tools {template <typename T>void hash_combine(::std::size_t& seed, const T& v) {static const ::std::hash<T> hasher;static constexpr ::std::size_t k_mul = 0x9ddfea08eb382d69ULL;::std::size_t a = (hasher(v) ^ seed) * k_mul;a ^= (a >> 47);::std::size_t b = (seed ^ a) * k_mul;b ^= (b >> 47);seed = b * k_mul;}}#line 11 "/home/anqooqie/.proconlib/tools/tuple_hash.hpp"namespace tools {template <typename... Ts>struct tuple_hash {template <::std::size_t I = sizeof...(Ts) - 1>::std::size_t operator()(const ::std::tuple<Ts...>& key) const {if constexpr (I == ::std::numeric_limits<::std::size_t>::max()) {static const ::std::size_t seed = ::tools::now();return seed;} else {::std::size_t seed = this->operator()<I - 1>(key);::tools::hash_combine(seed, ::std::get<I>(key));return seed;}}};}#line 14 "/home/anqooqie/.proconlib/tools/extend_hash.hpp"namespace std {template <class T1, class T2>struct hash<::std::pair<T1, T2>> {::std::size_t operator()(const ::std::pair<T1, T2>& key) const {static const ::tools::tuple_hash<T1, T2> hasher;return hasher(::std::make_tuple(key.first, key.second));}};template <class... Args>struct hash<::std::tuple<Args...>> {::std::size_t operator()(const ::std::tuple<Args...>& key) const {static const ::tools::tuple_hash<Args...> hasher;return hasher(key);}};}#line 23 "/home/anqooqie/.proconlib/tools/util.hpp"using ll = long long;using ull = unsigned long long;using i32 = ::std::int32_t;using u32 = ::std::uint32_t;using i64 = ::std::int64_t;using u64 = ::std::uint64_t;#define ALL(x) ::std::begin(x), ::std::end(x)#define REP(i, n) for (long long i = 0, i##_len = static_cast<long long>(n); i < i##_len; ++i)#line 1 "/home/anqooqie/.proconlib/lib/ac-library/atcoder/modint.hpp"#line 7 "/home/anqooqie/.proconlib/lib/ac-library/atcoder/modint.hpp"#ifdef _MSC_VER#include <intrin.h>#endif#line 1 "/home/anqooqie/.proconlib/lib/ac-library/atcoder/internal_math.hpp"#line 5 "/home/anqooqie/.proconlib/lib/ac-library/atcoder/internal_math.hpp"#ifdef _MSC_VER#include <intrin.h>#endifnamespace atcoder {namespace internal {// @param m `1 <= m`// @return x mod mconstexpr long long safe_mod(long long x, long long m) {x %= m;if (x < 0) x += m;return x;}// Fast modular multiplication by barrett reduction// Reference: https://en.wikipedia.org/wiki/Barrett_reduction// NOTE: reconsider after Ice Lakestruct barrett {unsigned int _m;unsigned long long im;// @param m `1 <= m`explicit barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}// @return munsigned int umod() const { return _m; }// @param a `0 <= a < m`// @param b `0 <= b < m`// @return `a * b % m`unsigned int mul(unsigned int a, unsigned int b) const {// [1] m = 1// a = b = im = 0, so okay// [2] m >= 2// im = ceil(2^64 / m)// -> im * m = 2^64 + r (0 <= r < m)// let z = a*b = c*m + d (0 <= c, d < m)// a*b * im = (c*m + d) * im = c*(im*m) + d*im = c*2^64 + c*r + d*im// c*r + d*im < m * m + m * im < m * m + 2^64 + m <= 2^64 + m * (m + 1) < 2^64 * 2// ((ab * im) >> 64) == c or c + 1unsigned long long z = a;z *= b;#ifdef _MSC_VERunsigned long long x;_umul128(z, im, &x);#elseunsigned long long x =(unsigned long long)(((unsigned __int128)(z)*im) >> 64);#endifunsigned long long y = x * _m;return (unsigned int)(z - y + (z < y ? _m : 0));}};// @param n `0 <= n`// @param m `1 <= m`// @return `(x ** n) % m`constexpr long long pow_mod_constexpr(long long x, long long n, int m) {if (m == 1) return 0;unsigned int _m = (unsigned int)(m);unsigned long long r = 1;unsigned long long y = safe_mod(x, m);while (n) {if (n & 1) r = (r * y) % _m;y = (y * y) % _m;n >>= 1;}return r;}// Reference:// M. Forisek and J. Jancina,// Fast Primality Testing for Integers That Fit into a Machine Word// @param n `0 <= n`constexpr bool is_prime_constexpr(int n) {if (n <= 1) return false;if (n == 2 || n == 7 || n == 61) return true;if (n % 2 == 0) return false;long long d = n - 1;while (d % 2 == 0) d /= 2;constexpr long long bases[3] = {2, 7, 61};for (long long a : bases) {long long t = d;long long y = pow_mod_constexpr(a, t, n);while (t != n - 1 && y != 1 && y != n - 1) {y = y * y % n;t <<= 1;}if (y != n - 1 && t % 2 == 0) {return false;}}return true;}template <int n> constexpr bool is_prime = is_prime_constexpr(n);// @param b `1 <= b`// @return pair(g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/gconstexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {a = safe_mod(a, b);if (a == 0) return {b, 0};// Contracts:// [1] s - m0 * a = 0 (mod b)// [2] t - m1 * a = 0 (mod b)// [3] s * |m1| + t * |m0| <= blong long s = b, t = a;long long m0 = 0, m1 = 1;while (t) {long long u = s / t;s -= t * u;m0 -= m1 * u; // |m1 * u| <= |m1| * s <= b// [3]:// (s - t * u) * |m1| + t * |m0 - m1 * u|// <= s * |m1| - t * u * |m1| + t * (|m0| + |m1| * u)// = s * |m1| + t * |m0| <= bauto tmp = s;s = t;t = tmp;tmp = m0;m0 = m1;m1 = tmp;}// by [3]: |m0| <= b/g// by g != b: |m0| < b/gif (m0 < 0) m0 += b / s;return {s, m0};}// Compile time primitive root// @param m must be prime// @return primitive root (and minimum in now)constexpr int primitive_root_constexpr(int m) {if (m == 2) return 1;if (m == 167772161) return 3;if (m == 469762049) return 3;if (m == 754974721) return 11;if (m == 998244353) return 3;int divs[20] = {};divs[0] = 2;int cnt = 1;int x = (m - 1) / 2;while (x % 2 == 0) x /= 2;for (int i = 3; (long long)(i)*i <= x; i += 2) {if (x % i == 0) {divs[cnt++] = i;while (x % i == 0) {x /= i;}}}if (x > 1) {divs[cnt++] = x;}for (int g = 2;; g++) {bool ok = true;for (int i = 0; i < cnt; i++) {if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {ok = false;break;}}if (ok) return g;}}template <int m> constexpr int primitive_root = primitive_root_constexpr(m);// @param n `n < 2^32`// @param m `1 <= m < 2^32`// @return sum_{i=0}^{n-1} floor((ai + b) / m) (mod 2^64)unsigned long long floor_sum_unsigned(unsigned long long n,unsigned long long m,unsigned long long a,unsigned long long b) {unsigned long long ans = 0;while (true) {if (a >= m) {ans += n * (n - 1) / 2 * (a / m);a %= m;}if (b >= m) {ans += n * (b / m);b %= m;}unsigned long long y_max = a * n + b;if (y_max < m) break;// y_max < m * (n + 1)// floor(y_max / m) <= nn = (unsigned long long)(y_max / m);b = (unsigned long long)(y_max % m);std::swap(m, a);}return ans;}} // namespace internal} // namespace atcoder#line 1 "/home/anqooqie/.proconlib/lib/ac-library/atcoder/internal_type_traits.hpp"#line 7 "/home/anqooqie/.proconlib/lib/ac-library/atcoder/internal_type_traits.hpp"namespace atcoder {namespace internal {#ifndef _MSC_VERtemplate <class T>using is_signed_int128 =typename std::conditional<std::is_same<T, __int128_t>::value ||std::is_same<T, __int128>::value,std::true_type,std::false_type>::type;template <class T>using is_unsigned_int128 =typename std::conditional<std::is_same<T, __uint128_t>::value ||std::is_same<T, unsigned __int128>::value,std::true_type,std::false_type>::type;template <class T>using make_unsigned_int128 =typename std::conditional<std::is_same<T, __int128_t>::value,__uint128_t,unsigned __int128>;template <class T>using is_integral = typename std::conditional<std::is_integral<T>::value ||is_signed_int128<T>::value ||is_unsigned_int128<T>::value,std::true_type,std::false_type>::type;template <class T>using is_signed_int = typename std::conditional<(is_integral<T>::value &&std::is_signed<T>::value) ||is_signed_int128<T>::value,std::true_type,std::false_type>::type;template <class T>using is_unsigned_int =typename std::conditional<(is_integral<T>::value &&std::is_unsigned<T>::value) ||is_unsigned_int128<T>::value,std::true_type,std::false_type>::type;template <class T>using to_unsigned = typename std::conditional<is_signed_int128<T>::value,make_unsigned_int128<T>,typename std::conditional<std::is_signed<T>::value,std::make_unsigned<T>,std::common_type<T>>::type>::type;#elsetemplate <class T> using is_integral = typename std::is_integral<T>;template <class T>using is_signed_int =typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,std::true_type,std::false_type>::type;template <class T>using is_unsigned_int =typename std::conditional<is_integral<T>::value &&std::is_unsigned<T>::value,std::true_type,std::false_type>::type;template <class T>using to_unsigned = typename std::conditional<is_signed_int<T>::value,std::make_unsigned<T>,std::common_type<T>>::type;#endiftemplate <class T>using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;template <class T>using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;template <class T> using to_unsigned_t = typename to_unsigned<T>::type;} // namespace internal} // namespace atcoder#line 14 "/home/anqooqie/.proconlib/lib/ac-library/atcoder/modint.hpp"namespace atcoder {namespace internal {struct modint_base {};struct static_modint_base : modint_base {};template <class T> using is_modint = std::is_base_of<modint_base, T>;template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;} // namespace internaltemplate <int m, std::enable_if_t<(1 <= m)>* = nullptr>struct static_modint : internal::static_modint_base {using mint = static_modint;public:static constexpr int mod() { return m; }static mint raw(int v) {mint x;x._v = v;return x;}static_modint() : _v(0) {}template <class T, internal::is_signed_int_t<T>* = nullptr>static_modint(T v) {long long x = (long long)(v % (long long)(umod()));if (x < 0) x += umod();_v = (unsigned int)(x);}template <class T, internal::is_unsigned_int_t<T>* = nullptr>static_modint(T v) {_v = (unsigned int)(v % umod());}unsigned int val() const { return _v; }mint& operator++() {_v++;if (_v == umod()) _v = 0;return *this;}mint& operator--() {if (_v == 0) _v = umod();_v--;return *this;}mint operator++(int) {mint result = *this;++*this;return result;}mint operator--(int) {mint result = *this;--*this;return result;}mint& operator+=(const mint& rhs) {_v += rhs._v;if (_v >= umod()) _v -= umod();return *this;}mint& operator-=(const mint& rhs) {_v -= rhs._v;if (_v >= umod()) _v += umod();return *this;}mint& operator*=(const mint& rhs) {unsigned long long z = _v;z *= rhs._v;_v = (unsigned int)(z % umod());return *this;}mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }mint operator+() const { return *this; }mint operator-() const { return mint() - *this; }mint pow(long long n) const {assert(0 <= n);mint x = *this, r = 1;while (n) {if (n & 1) r *= x;x *= x;n >>= 1;}return r;}mint inv() const {if (prime) {assert(_v);return pow(umod() - 2);} else {auto eg = internal::inv_gcd(_v, m);assert(eg.first == 1);return eg.second;}}friend mint operator+(const mint& lhs, const mint& rhs) {return mint(lhs) += rhs;}friend mint operator-(const mint& lhs, const mint& rhs) {return mint(lhs) -= rhs;}friend mint operator*(const mint& lhs, const mint& rhs) {return mint(lhs) *= rhs;}friend mint operator/(const mint& lhs, const mint& rhs) {return mint(lhs) /= rhs;}friend bool operator==(const mint& lhs, const mint& rhs) {return lhs._v == rhs._v;}friend bool operator!=(const mint& lhs, const mint& rhs) {return lhs._v != rhs._v;}private:unsigned int _v;static constexpr unsigned int umod() { return m; }static constexpr bool prime = internal::is_prime<m>;};template <int id> struct dynamic_modint : internal::modint_base {using mint = dynamic_modint;public:static int mod() { return (int)(bt.umod()); }static void set_mod(int m) {assert(1 <= m);bt = internal::barrett(m);}static mint raw(int v) {mint x;x._v = v;return x;}dynamic_modint() : _v(0) {}template <class T, internal::is_signed_int_t<T>* = nullptr>dynamic_modint(T v) {long long x = (long long)(v % (long long)(mod()));if (x < 0) x += mod();_v = (unsigned int)(x);}template <class T, internal::is_unsigned_int_t<T>* = nullptr>dynamic_modint(T v) {_v = (unsigned int)(v % mod());}unsigned int val() const { return _v; }mint& operator++() {_v++;if (_v == umod()) _v = 0;return *this;}mint& operator--() {if (_v == 0) _v = umod();_v--;return *this;}mint operator++(int) {mint result = *this;++*this;return result;}mint operator--(int) {mint result = *this;--*this;return result;}mint& operator+=(const mint& rhs) {_v += rhs._v;if (_v >= umod()) _v -= umod();return *this;}mint& operator-=(const mint& rhs) {_v += mod() - rhs._v;if (_v >= umod()) _v -= umod();return *this;}mint& operator*=(const mint& rhs) {_v = bt.mul(_v, rhs._v);return *this;}mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }mint operator+() const { return *this; }mint operator-() const { return mint() - *this; }mint pow(long long n) const {assert(0 <= n);mint x = *this, r = 1;while (n) {if (n & 1) r *= x;x *= x;n >>= 1;}return r;}mint inv() const {auto eg = internal::inv_gcd(_v, mod());assert(eg.first == 1);return eg.second;}friend mint operator+(const mint& lhs, const mint& rhs) {return mint(lhs) += rhs;}friend mint operator-(const mint& lhs, const mint& rhs) {return mint(lhs) -= rhs;}friend mint operator*(const mint& lhs, const mint& rhs) {return mint(lhs) *= rhs;}friend mint operator/(const mint& lhs, const mint& rhs) {return mint(lhs) /= rhs;}friend bool operator==(const mint& lhs, const mint& rhs) {return lhs._v == rhs._v;}friend bool operator!=(const mint& lhs, const mint& rhs) {return lhs._v != rhs._v;}private:unsigned int _v;static internal::barrett bt;static unsigned int umod() { return bt.umod(); }};template <int id> internal::barrett dynamic_modint<id>::bt(998244353);using modint998244353 = static_modint<998244353>;using modint1000000007 = static_modint<1000000007>;using modint = dynamic_modint<-1>;namespace internal {template <class T>using is_static_modint = std::is_base_of<internal::static_modint_base, T>;template <class T>using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;template <class> struct is_dynamic_modint : public std::false_type {};template <int id>struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};template <class T>using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;} // namespace internal} // namespace atcoder#line 1 "/home/anqooqie/.proconlib/lib/ac-library/atcoder/segtree.hpp"#line 8 "/home/anqooqie/.proconlib/lib/ac-library/atcoder/segtree.hpp"#line 1 "/home/anqooqie/.proconlib/lib/ac-library/atcoder/internal_bit.hpp"#ifdef _MSC_VER#include <intrin.h>#endif#if __cplusplus >= 202002L#include <bit>#endifnamespace atcoder {namespace internal {#if __cplusplus >= 202002Lusing std::bit_ceil;#else// @return same with std::bit::bit_ceilunsigned int bit_ceil(unsigned int n) {unsigned int x = 1;while (x < (unsigned int)(n)) x *= 2;return x;}#endif// @param n `1 <= n`// @return same with std::bit::countr_zeroint countr_zero(unsigned int n) {#ifdef _MSC_VERunsigned long index;_BitScanForward(&index, n);return index;#elsereturn __builtin_ctz(n);#endif}// @param n `1 <= n`// @return same with std::bit::countr_zeroconstexpr int countr_zero_constexpr(unsigned int n) {int x = 0;while (!(n & (1 << x))) x++;return x;}} // namespace internal} // namespace atcoder#line 10 "/home/anqooqie/.proconlib/lib/ac-library/atcoder/segtree.hpp"namespace atcoder {#if __cplusplus >= 201703Ltemplate <class S, auto op, auto e> struct segtree {static_assert(std::is_convertible_v<decltype(op), std::function<S(S, S)>>,"op must work as S(S, S)");static_assert(std::is_convertible_v<decltype(e), std::function<S()>>,"e must work as S()");#elsetemplate <class S, S (*op)(S, S), S (*e)()> struct segtree {#endifpublic:segtree() : segtree(0) {}explicit segtree(int n) : segtree(std::vector<S>(n, e())) {}explicit segtree(const std::vector<S>& v) : _n(int(v.size())) {size = (int)internal::bit_ceil((unsigned int)(_n));log = internal::countr_zero((unsigned int)size);d = std::vector<S>(2 * size, e());for (int i = 0; i < _n; i++) d[size + i] = v[i];for (int i = size - 1; i >= 1; i--) {update(i);}}void set(int p, S x) {assert(0 <= p && p < _n);p += size;d[p] = x;for (int i = 1; i <= log; i++) update(p >> i);}S get(int p) const {assert(0 <= p && p < _n);return d[p + size];}S prod(int l, int r) const {assert(0 <= l && l <= r && r <= _n);S sml = e(), smr = e();l += size;r += size;while (l < r) {if (l & 1) sml = op(sml, d[l++]);if (r & 1) smr = op(d[--r], smr);l >>= 1;r >>= 1;}return op(sml, smr);}S all_prod() const { return d[1]; }template <bool (*f)(S)> int max_right(int l) const {return max_right(l, [](S x) { return f(x); });}template <class F> int max_right(int l, F f) const {assert(0 <= l && l <= _n);assert(f(e()));if (l == _n) return _n;l += size;S sm = e();do {while (l % 2 == 0) l >>= 1;if (!f(op(sm, d[l]))) {while (l < size) {l = (2 * l);if (f(op(sm, d[l]))) {sm = op(sm, d[l]);l++;}}return l - size;}sm = op(sm, d[l]);l++;} while ((l & -l) != l);return _n;}template <bool (*f)(S)> int min_left(int r) const {return min_left(r, [](S x) { return f(x); });}template <class F> int min_left(int r, F f) const {assert(0 <= r && r <= _n);assert(f(e()));if (r == 0) return 0;r += size;S sm = e();do {r--;while (r > 1 && (r % 2)) r >>= 1;if (!f(op(d[r], sm))) {while (r < size) {r = (2 * r + 1);if (f(op(d[r], sm))) {sm = op(d[r], sm);r--;}}return r + 1 - size;}sm = op(d[r], sm);} while ((r & -r) != r);return 0;}private:int _n, size, log;std::vector<S> d;void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }};} // namespace atcoder#line 1 "/home/anqooqie/.proconlib/tools/less_by_first.hpp"#line 5 "/home/anqooqie/.proconlib/tools/less_by_first.hpp"namespace tools {class less_by_first {public:template <class T1, class T2>bool operator()(const ::std::pair<T1, T2>& x, const ::std::pair<T1, T2>& y) const {return x.first < y.first;}};}#line 5 "main.cpp"using mint = atcoder::modint1000000007;struct monoid {using T = std::pair<ll, mint>;static T op(const T& x, const T& y) {return x.first == y.first ? T(x.first, x.second + y.second) : std::max(x, y, tools::less_by_first{});}static T e() {return T(0, mint::raw(0));}};int main() {std::cin.tie(nullptr);std::ios_base::sync_with_stdio(false);ll N;std::cin >> N;std::vector<ll> A(N);std::cin >> A;std::vector<std::pair<ll, ll>> sorted;REP(i, N) {sorted.emplace_back(A[i], -i);}std::sort(ALL(sorted));REP(i, N) {A[i] = std::distance(sorted.begin(), std::lower_bound(ALL(sorted), std::make_pair(A[i], -i)));}atcoder::segtree<typename monoid::T, monoid::op, monoid::e> dp(N);REP(i, N) {const auto [n, k] = dp.prod(0, A[i]);dp.set(A[i], std::make_pair(n + 1, n == 0 ? mint::raw(1) : k));}std::cout << dp.all_prod().second.val() << '\n';return 0;}