結果
問題 | No.992 最長増加部分列の数え上げ |
ユーザー |
|
提出日時 | 2024-11-09 19:55:27 |
言語 | C++17(gcc12) (gcc 12.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 311 ms / 2,000 ms |
コード長 | 45,587 bytes |
コンパイル時間 | 20,067 ms |
コンパイル使用メモリ | 384,388 KB |
最終ジャッジ日時 | 2025-02-25 03:22:51 |
ジャッジサーバーID (参考情報) |
judge4 / judge1 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 42 |
ソースコード
#pragma region Macros#pragma GCC optimize("O3,unroll-loops")#pragma GCC target("sse,sse2,sse3,ssse3,sse4,fma,mmx,abm,bmi,bmi2,popcnt,lzcnt")#pragma GCC target("avx2") // CF, CodeChef, HOJ ではコメントアウト#include <bits/extc++.h>// #include <atcoder/all>// using namespace atcoder;using namespace std;using namespace __gnu_pbds;// #include <boost/multiprecision/cpp_dec_float.hpp>// #include <boost/multiprecision/cpp_int.hpp>// namespace mp = boost::multiprecision;// using Bint = mp::cpp_int;// using Bdouble = mp::number<mp::cpp_dec_float<256>>;// Bdouble Beps = 0.00000000000000000000000000000001; // 1e-32// const bool equals(Bdouble a, Bdouble b) { return mp::fabs(a - b) < Beps; }#define pb emplace_back// #define int ll#define endl '\n'// #define sqrt __builtin_sqrtl// #define cbrt __builtin_cbrtl// #define hypot __builtin_hypotlusing ll = long long;using ld = long double;const ld PI = acosl(-1);const int INF = 1 << 30;const ll INFL = 1LL << 61;// const int MOD = 998244353;const int MOD = 1000000007;const ld EPS = 1e-10;const bool equals(ld a, ld b) { return fabs((a) - (b)) < EPS; }const vector<int> dx = {0, 1, 0, -1, 1, 1, -1, -1, 0}; // → ↓ ← ↑ ↘ ↙ ↖ ↗ 自const vector<int> dy = {1, 0, -1, 0, 1, -1, -1, 1, 0};#define EC intstruct Edge {int from, to;EC cost;Edge() {}// Edge() : from(-1), to(-1), cost(-1) {}Edge(int to, EC cost) : to(to), cost(cost) {}Edge(int from, int to, EC cost) : from(from), to(to), cost(cost) {}bool operator ==(const Edge &e) {return this->from == e.from && this->to == e.to && this->cost == e.cost;}bool operator !=(const Edge &e) {return this->from != e.from or this->to != e.to or this->cost != e.cost;}bool operator <(const Edge &e) { return this->cost < e.cost; }bool operator >(const Edge &e) { return this->cost > e.cost; }};chrono::system_clock::time_point start;__attribute__((constructor))void constructor() {ios::sync_with_stdio(false);cin.tie(nullptr);cout << fixed << setprecision(10);start = chrono::system_clock::now();}random_device seed_gen;mt19937_64 rng(seed_gen());uniform_int_distribution<int> dist_x(0, 1e9);struct RNG {unsigned Int() {return dist_x(rng);}unsigned Int(unsigned l, unsigned r) {return dist_x(rng) % (r - l + 1) + l;}ld Double() {return ld(dist_x(rng)) / 1e9;}} rnd;namespace bit_function {using i64 = ll;// using i64 = uint64_t;// bit演算, x==0の場合は例外処理した方がよさそう. 区間は [l, r)i64 lrmask(int l, int r) { return (1LL << r) - (1LL << l); }i64 sub_bit(i64 x, int l, int r) { i64 b = x & ((1LL << r) - (1LL << l)); return b >> l; } // r溢れ可i64 bit_width(i64 x) { return 64 - __builtin_clzll(x) + (x == 0); }i64 popcount(i64 x) { return __builtin_popcountll(x); }i64 popcount(i64 x, int l, int r) { return __builtin_popcountll(sub_bit(x, l, r)); }i64 unpopcount(i64 x) { return bit_width(x) - __builtin_popcountll(x); } // 最上位bitより下のみi64 unpopcount(i64 x, int l, int r) { return r - l - __builtin_popcountll(sub_bit(x, l, r)); } // 最上位bitより上も含まれうるbool is_pow2(i64 x) { return __builtin_popcountll(x) == 1; } // xが負のときは常にfalsebool is_pow4(i64 x) { return __builtin_popcountll(x) == 1 && __builtin_ctz(x) % 2 == 0; }//bool is_pow4(ll x) { return __builtin_popcountll(x) == 1 && (x&0x55555555); }int top_bit(i64 x) { return 63 - __builtin_clzll(x);} // 2^kの位 (x > 0)int bot_bit(i64 x) { return __builtin_ctzll(x);} // 2^kの位 (x > 0)int next_bit(i64 x, int k) { // upper_boundx >>= (k + 1);int pos = k + 1;while (x > 0) {if (x & 1) return pos;x >>= 1;pos++;}return -1;}int prev_bit(i64 x, int k) {// k = min(k, bit_width(x)); ?int pos = 0;while (x > 0 && pos < k) {if (x & 1) {if (pos < k) return pos;}x >>= 1;pos++;}return -1;}int kth_bit(i64 x, int k) { // kは1-indexedint pos = 0, cnt = 0;while (x > 0) {if (x & 1) {cnt++;if (cnt == k) return pos;}x >>= 1;pos++;}return -1;}i64 msb(i64 x) { if (x == 0) return 0; return 1LL << (63 - __builtin_clzll(x)); } // maski64 lsb(i64 x) { return (x & -x); } // maskint countl_zero(i64 x) { return __builtin_clzll(x); }int countl_one(i64 x) { // countl_oneと定義が異なるので注意i64 ret = 0, k = 63 - __builtin_clzll(x);while (k != -1 && (x & (1LL << k))) { k--; ret++; }return ret;}int countr_zero(i64 x) { return __builtin_ctzll(x); } // x=0のとき64int countr_one(i64 x) { int ret = 0; while (x & 1) { x >>= 1; ret++; } return ret; }// int countr_one(ll x) { return __builtin_popcount(x ^ (x & -~x));i64 l_one(i64 x) { // 最上位で連なってる1のmaskif (x == 0) return 0;i64 ret = 0, k = 63 - __builtin_clzll(x);while (k != -1 && (x & (1LL << k))) { ret += 1LL << k; k--; }return ret;}int floor_log2(i64 x) { return 63 - __builtin_clzll(x); } // top_bitint ceil_log2(i64 x) { return 64 - __builtin_clzll(x - 1); }i64 bit_floor(i64 x) { if (x == 0) return 0; return 1LL << (63 - __builtin_clzll(x)); } // msbi64 bit_ceil(i64 x) { if (x == 0) return 0; return 1LL << (64 - __builtin_clzll(x - 1)); }i64 rotl(i64 x, int k) { // 有効bit内でrotate. オーバーフロー注意i64 w = bit_width(x); k %= w;return ((x << k) | (x >> (w - k))) & ((1LL << w) - 1);}// i64 rotl(i64 x, i64 l, i64 m, i64 r) {}i64 rotr(i64 x, int k) {i64 w = bit_width(x); k %= w;return ((x >> k) | (x << (w - k))) & ((1LL << w) - 1);}// i64 rotr(i64 x, i64 l, i64 m, i64 r) {}i64 bit_reverse(i64 x) { // 有効bit内で左右反転i64 r = 0, w = bit_width(x);for (i64 i = 0; i < w; i++) r |= ((x >> i) & 1) << (w - i - 1);return r;}// i64 bit_reverse(i64 x, int l, int r) {}bool is_palindrome(i64 x) { return x == bit_reverse(x); }bool is_palindrome(i64 x, int l, int r) { i64 b = sub_bit(x, l, r); return b == bit_reverse(b); }i64 concat(i64 a, i64 b) { return (a << bit_width(b)) | b; } // オーバーフロー注意i64 erase(i64 x, int l, int r) { return x >> r << l | x & ((1LL << l) - 1); } // [l, r) をカットi64 hamming(i64 a, i64 b) { return __builtin_popcountll(a ^ b); }i64 hamming(i64 a, i64 b, int l, int r) { return __builtin_popcountll(sub_bit(a, l, r) ^ sub_bit(b, l, r)); }i64 compcount(i64 x) { return (__builtin_popcountll(x ^ (x >> 1)) + (x & 1)) / 2; }i64 compcount2(i64 x) { return compcount(x & (x >> 1)); } // 長さ2以上の連結成分の個数i64 adjacount(i64 x) { return __builtin_popcountll(x & (x >> 1)); } // 隣接する1のペアの個数i64 next_combination(i64 x) {i64 t = x | (x - 1); return (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctzll(x) + 1));}} using namespace bit_function;namespace util_function {namespace Std = std;__int128_t POW(__int128_t x, int n) {__int128_t ret = 1;assert(n >= 0);if (x == 1 or n == 0) ret = 1;else if (x == -1 && n % 2 == 0) ret = 1;else if (x == -1) ret = -1;else if (n % 2 == 0) {// assert(x < INFL);ret = POW(x * x, n / 2);} else {// assert(x < INFL);ret = x * POW(x, n - 1);}return ret;}int per(int x, int y) { // x = qy + r (0 <= r < y) を満たすqassert(y != 0);if (x >= 0 && y > 0) return x / y;if (x >= 0 && y < 0) return x / y - (x % y < 0);if (x < 0 && y < 0) return x / y + (x % y < 0);return x / y - (x % y < 0); // (x < 0 && y > 0)}int mod(int x, int y) { // x = qy + r (0 <= r < y) を満たすrassert(y != 0);return x - y * per(x, y);} // https://yukicoder.me/problems/no/2781int floor(int x, int y) { // (ld)x / y 以下の最大の整数assert(y != 0);if (y < 0) x = -x, y = -y;return x >= 0 ? x / y : (x + 1) / y - 1;}int ceil(int x, int y) { // (ld)x / y 以上の最小の整数assert(y != 0);if (y < 0) x = -x, y = -y;return x > 0 ? (x - 1) / y + 1 : x / y;}int round(int x, int y) { // (ld)x / y を小数第1位について四捨五入assert(y != 0);return (x * 2 + y) / (y * 2);}int round(int x, int y, int k) { // (ld)x / y を10^kの位に関して四捨五入assert(y != 0 && k >= 0);if (k == 0) return (x * 2 + y) / (y * 2);x /= y * POW(10, k - 1);if (x % 10 >= 5) return (x + 10 - x % 10) * POW(10, k - 1);return x * POW(10, k - 1);}int round2(int x, int y) { // 五捨五超入 // 未verifyassert(y != 0);if (y < 0) y = -y, x = -x;int z = x / y;if ((z * 2 + 1) * y <= y * 2) z++;return z;}ld round(ld x, int k) { // xを10^kの位に関して四捨五入.// x += EPS;ld d = pow(10, -k);return Std::round(x * d) / d;}ld floor(ld x, int k) { // xを10^kの位に関してflooring// x += EPS;ld d = pow(10, -k);return Std::floor(x * d) / d; // 未verify}ld ceil(ld x, int k) { // xを10^kの位に関してceiling// x -= EPS;ld d = pow(10, -k);return Std::ceil(x * d) / d; // 未verify}// int kth(int x, int y, int k) { // x / yの10^kの位の桁// }int floor(ld x, ld y) { // 誤差対策TODOassert(!equals(y, 0));return Std::floor(x / y);// floor(x) = ceil(x - 1) という話も}int ceil(ld x, ld y) { // 誤差対策TODO // ceil(p/q) = -floor(-(p/q))らしいassert(!equals(y, 0));return Std::ceil(x / y);// ceil(x) = floor(x + 1)}int perl(ld x, ld y) { // x = qy + r (0 <= r < y, qは整数) を満たす q// 未verify. 誤差対策TODO. EPS外してもいいかも。assert(!equals(y, 0));if (x >= 0 && y > 0) return Std::floor(x / y)+EPS;if (x >= 0 && y < 0) return -Std::floor(x / fabs(y));if (x < 0 && y < 0) return Std::floor(x / y) + (x - Std::floor(x/y)*y < -EPS);return Std::floor(x / y) - (x - Std::floor(x/y)*y < -EPS); // (x < 0 && y > 0)}ld modl(ld x, ld y) { // x = qy + r (0 <= r < y, qは整数) を満たす r// 未verify. 誤差対策TODO. -0.0が返りうる。assert(!equals(y, 0));if (x >= 0) return x - fabs(y)*fabs(per(x, y));return x - fabs(y)*floor(x, fabs(y));}int seisuu(ld x) { return (int)x; } // 整数部分. 誤差対策TODOint modf(ld x) {if (x < 0) return ceill(x);else return floorl(x);}// 正なら+EPS, 負なら-EPSしてから、文字列に直して小数点以下を捨てる?int seisuu(int x, int y) {assert(y != 0);return x / y;}int seisuu(ld x, ld y) { // 誤差対策TODOassert(!equals(y, 0));return (int)(x / y);}int floor_log(int base, int x) {assert(base >= 2);int ret = 0, now = 1;while (now <= x) {now *= base;if (now <= x) ret++;}return ret;}int ceil_log(int base, int x) {assert(base >= 2);int ret = 0, now = 1;while (now < x) {now *= base;ret++;}return ret;}template <class T> pair<T, T> max(const pair<T, T> &a, const pair<T, T> &b) {if (a.first > b.first or a.first == b.first && a.second > b.second) return a;return b;}template <class T> pair<T, T> min(const pair<T, T> &a, const pair<T, T> &b) {if (a.first < b.first or a.first == b.first && a.second < b.second) return a;return b;}template <class T> bool chmax(T &a, const T &b) {if (a < b) { a = b; return true; } return false;}template <class T> bool chmin(T &a, const T &b) {if (a > b) { a = b; return true; } return false;}template <class T> bool chmax(pair<T, T> &a, const pair<T, T> &b) {if (a.first < b.first or a.first == b.first && a.second < b.second) { a = b; return true; }return false;}template <class T> bool chmin(pair<T, T> &a, const pair<T, T> &b) {if (a.first > b.first or a.first == b.first && a.second > b.second) { a = b; return true; }return false;}template <class T> T mid(T a, T b, T c) { // 誤差対策TODOreturn a + b + c - Std::max({a, b, c}) - Std::min({a, b, c});}template <typename T, typename... Args>void Sort(T& a, T& b, T& c, Args&... args) {vector<T> vec = {a, b, c, args...};sort(vec.begin(), vec.end());auto it = vec.begin();a = *it++; b = *it++; c = *it++;int dummy[] = { (args = *it++, 0)... };static_cast<void>(dummy);}template <typename T, typename... Args>void Sortr(T& a, T& b, T& c, Args&... args) {vector<T> vec = {a, b, c, args...};sort(vec.rbegin(), vec.rend());auto it = vec.begin();a = *it++; b = *it++; c = *it++;int dummy[] = { (args = *it++, 0)... };static_cast<void>(dummy);}template <class T>void sort(vector<T> &A, vector<T> &B) {vector<pair<T, T>> P(A.size());for (int i = 0; i < A.size(); i++) P[i] = {A[i], B[i]};sort(P.begin(), P.end());for (int i = 0; i < A.size(); i++) A[i] = P[i].first, B[i] = P[i].second;}istream &operator >>(istream &is, __int128_t& x) {string S; is >> S;__int128_t ret = 0;int f = 1;if (S[0] == '-') f = -1;for (int i = 0; i < S.length(); i++)if ('0' <= S[i] && S[i] <= '9')ret = ret * 10 + S[i] - '0';x = ret * f;return (is);}ostream &operator <<(ostream &os, __int128_t x) {ostream::sentry s(os);if (s) {__uint128_t tmp = x < 0 ? -x : x;char buffer[128]; char *d = end(buffer);do {--d; *d = "0123456789"[tmp % 10]; tmp /= 10;} while (tmp != 0);if (x < 0) { --d; *d = '-'; }int len = end(buffer) - d;if (os.rdbuf()->sputn(d, len) != len) os.setstate(ios_base::badbit);}return os;}__int128_t sto128(const string &S) {__int128_t ret = 0; int f = 1;if (S[0] == '-') f = -1;for (int i = 0; i < S.length(); i++)if ('0' <= S[i] && S[i] <= '9') ret = ret * 10 + S[i] - '0';return ret * f;}__int128_t gcd(__int128_t a, __int128_t b) { return b ? gcd(b, a % b) : a; }__int128_t lcm(__int128_t a, __int128_t b) {return a / gcd(a, b) * b;// lcmが__int128_tに収まる必要あり}string to_string(double x, int k) { // 小数第k+1を四捨五入して小数第k位までを出力// 切り捨てがほしい場合は to_string(x, k+1) として pop_back() すればよい?ostringstream os;os << fixed << setprecision(k) << x;return os.str();}string to_string(__int128_t x) {string ret = "";if (x < 0) { ret += "-"; x *= -1; }while (x) { ret += (char)('0' + x % 10); x /= 10; }reverse(ret.begin(), ret.end());return ret;}string to_string(char c) { string s = ""; s += c; return s; }} using namespace util_function;struct custom_hash {static uint64_t splitmix64(uint64_t x) {x += 0x9e3779b97f4a7c15;x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;x = (x ^ (x >> 27)) * 0x94d049bb133111eb;return x ^ (x >> 31);}size_t operator()(uint64_t x) const {static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();return splitmix64(x + FIXED_RANDOM);}};template<class T> size_t HashCombine(const size_t seed,const T &v) {return seed^(hash<T>()(v)+0x9e3779b9+(seed<<6)+(seed>>2));}template<class T,class S> struct hash<pair<T,S>>{size_t operator()(const pair<T,S> &keyval) const noexcept {return HashCombine(hash<T>()(keyval.first), keyval.second);}};template<class T> struct hash<vector<T>>{size_t operator()(const vector<T> &keyval) const noexcept {size_t s=0;for (auto&& v: keyval) s=HashCombine(s,v);return s;}};template<int N> struct HashTupleCore{template<class Tuple> size_t operator()(const Tuple &keyval) const noexcept{size_t s=HashTupleCore<N-1>()(keyval);return HashCombine(s,get<N-1>(keyval));}};template <> struct HashTupleCore<0>{template<class Tuple> size_t operator()(const Tuple &keyval) const noexcept{ return 0; }};template<class... Args> struct hash<tuple<Args...>>{size_t operator()(const tuple<Args...> &keyval) const noexcept {return HashTupleCore<tuple_size<tuple<Args...>>::value>()(keyval);}};template<typename T>class Compress {public:int sz = 0;vector<T> uniqV;Compress() {}template<typename... Vecs>Compress(const Vecs&... vecs) {(uniqV.insert(uniqV.end(), vecs.begin(), vecs.end()), ...);sort(uniqV.begin(), uniqV.end());uniqV.erase(unique(uniqV.begin(), uniqV.end()), uniqV.end());sz = uniqV.size();}vector<int> zip(const vector<T> &V) {vector<int> ret(V.size());for (int i = 0; i < V.size(); i++) {ret[i] = encode(V[i]);}return ret;}vector<T> unzip(const vector<int> &V) {vector<T> ret(V.size());for (int i = 0; i < V.size(); i++) {ret[i] = decode(V[i]);}return ret;}int size() { return sz; }int encode(T x) {auto it = lower_bound(uniqV.begin(), uniqV.end(), x);return it - uniqV.begin();}T decode(int x) {if (x < 0 or x >= uniqV.size()) return -1; // xが範囲外の場合return uniqV[x];}};class UnionFind {public:UnionFind() = default;UnionFind(int N) : par(N), sz(N, 1) {iota(par.begin(), par.end(), 0);}int root(int x) {if (par[x] == x) return x;return (par[x] = root(par[x]));}bool unite(int x, int y) {int rx = root(x);int ry = root(y);if (rx == ry) return false;if (sz[rx] < sz[ry]) swap(rx, ry);sz[rx] += sz[ry];par[ry] = rx;return true;}bool issame(int x, int y) { return (root(x) == root(y)); }int size(int x) { return sz[root(x)]; }vector<vector<int>> groups(int N) {vector<vector<int>> G(N);for (int x = 0; x < N; x++) {G[root(x)].push_back(x);}G.erase( remove_if(G.begin(), G.end(),[&](const vector<int>& V) { return V.empty(); }), G.end());return G;}private:vector<int> par, sz;};template<typename T> struct BIT {int N; // 要素数vector<T> bit[2]; // データの格納先BIT(int N_, int x = 0) {N = N_ + 1;bit[0].assign(N, 0); bit[1].assign(N, 0);if (x != 0) {for (int i = 0; i < N; i++) add(i, x);}}BIT(const vector<T> &A) {N = A.size() + 1;bit[0].assign(N, 0); bit[1].assign(N, 0);for (int i = 0; i < (int)A.size(); i++) add(i, A[i]);}void add_sub(int p, int i, T x) {while (i < N) { bit[p][i] += x; i += (i & -i); }}void add(int l, int r, T x) {add_sub(0, l + 1, -x * l); add_sub(0, r + 1, x * r);add_sub(1, l + 1, x); add_sub(1, r + 1, -x);}void add(int i, T x) { add(i, i + 1, x); }T sum_sub(int p, int i) {T ret = 0;while (i > 0) { ret += bit[p][i]; i -= (i & -i); }return ret;}T sum(int i) { return sum_sub(0, i) + sum_sub(1, i) * i; }T sum(int l, int r) { return sum(r) - sum(l); }T get(int i) { return sum(i, i + 1); }void set(int i, T x) { T s = get(i); add(i, -s + x); }};template<int mod> class Modint {public:int val = 0;Modint(int x = 0) { while (x < 0) x += mod; val = x % mod; }Modint(const Modint &r) { val = r.val; }Modint operator -() { return Modint(-val); } // 単項Modint operator +(const Modint &r) { return Modint(*this) += r; }Modint operator +(const int &q) { Modint r(q); return Modint(*this) += r; }Modint operator -(const Modint &r) { return Modint(*this) -= r; }Modint operator -(const int &q) { Modint r(q); return Modint(*this) -= r; }Modint operator *(const Modint &r) { return Modint(*this) *= r; }Modint operator *(const int &q) { Modint r(q); return Modint(*this) *= r; }Modint operator /(const Modint &r) { return Modint(*this) /= r; }Modint operator /(const int &q) { Modint r(q); return Modint(*this) /= r; }Modint& operator ++() { val++; if (val >= mod) val -= mod; return *this; } // 前置Modint operator ++(signed) { ++*this; return *this; } // 後置Modint& operator --() { val--; if (val < 0) val += mod; return *this; }Modint operator --(signed) { --*this; return *this; }Modint &operator +=(const Modint &r) { val += r.val; if (val >= mod) val -= mod; return *this; }Modint &operator +=(const int &q) { Modint r(q); val += r.val; if (val >= mod) val -= mod; return *this; }Modint &operator -=(const Modint &r) { if (val < r.val) val += mod; val -= r.val; return *this; }Modint &operator -=(const int &q) { Modint r(q); if (val < r.val) val += mod; val -= r.val; return *this; }Modint &operator *=(const Modint &r) { val = val * r.val % mod; return *this; }Modint &operator *=(const int &q) { Modint r(q); val = val * r.val % mod; return *this; }Modint &operator /=(const Modint &r) {int a = r.val, b = mod, u = 1, v = 0;while (b) {int t = a / b; a -= t * b; swap(a, b); u -= t * v; swap(u, v);}val = val * u % mod; if (val < 0) val += mod;return *this;}Modint &operator /=(const int &q) {Modint r(q); int a = r.val, b = mod, u = 1, v = 0;while (b) {int t = a / b; a -= t * b; swap(a, b); u -= t * v; swap(u, v);}val = val * u % mod; if (val < 0) val += mod;return *this;}bool operator ==(const Modint& r) { return this -> val == r.val; }bool operator <(const Modint& r) { return this -> val < r.val; }bool operator >(const Modint& r) { return this -> val > r.val; }bool operator !=(const Modint& r) { return this -> val != r.val; }friend istream &operator >>(istream &is, Modint& x) {int t; is >> t; x = t; return (is);}friend ostream &operator <<(ostream &os, const Modint& x) {return os << x.val;}};using mint = Modint<MOD>;mint modpow(const mint &x, int n) {if (n < 0) return (mint)1 / modpow(x, -n); // 未verifyassert(n >= 0);if (n == 0) return 1;mint t = modpow(x, n / 2);t = t * t;if (n & 1) t = t * x;return t;}int modpow(__int128_t x, int n, int mod) {if (n == 0 && mod == 1) return 0;assert(n >= 0 && mod > 0); // TODO: n <= -1__int128_t ret = 1;while (n > 0) {if (n % 2 == 1) ret = ret * x % mod;x = x * x % mod;n /= 2;}return ret;}// int modinv(__int128_t x, int mod) { //// assert(mod > 0);// // assert(x > 0);// if (x == 1 or x == 0) return 1;// return mod - modinv(mod % x, mod) * (mod / x) % mod;// }vector<mint> _fac, _finv, _inv;void COMinit(int N) {_fac.resize(N + 1); _finv.resize(N + 1); _inv.resize(N + 1);_fac[0] = _fac[1] = 1; _finv[0] = _finv[1] = 1; _inv[1] = 1;for (int i = 2; i <= N; i++) {_fac[i] = _fac[i-1] * mint(i);_inv[i] = -_inv[MOD % i] * mint(MOD / i);_finv[i] = _finv[i - 1] * _inv[i];}}mint FAC(int N) {if (N < 0) return 0; return _fac[N];}mint FACinv(int N) {if (N < 0) return 0; return _finv[N];}mint COM(int N, int K) {if (N < K) return 0; if (N < 0 or K < 0) return 0;return _fac[N] * _finv[K] * _finv[N - K];}mint COMinv(int N, int K) {if (N < K) return 0; if (N < 0 or K < 0) return 0;return _finv[N] * _fac[K] * _fac[N - K];}mint MCOM(const vector<int> &V) {int N = 0;for (int i = 0; i < V.size(); i++) N += V[i];mint ret = _fac[N];for (int i = 0; i < V.size(); i++) ret *= _finv[V[i]];return ret;}mint PERM(int N, int K) {if (N < K) return 0; if (N < 0 or K < 0) return 0;return _fac[N] * _finv[N - K];}mint NHK(int N, int K) { // initのサイズに注意if (N == 0 && K == 0) return 1;return COM(N + K - 1, K);}#pragma endregionnamespace 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 internalnamespace 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 < 2^31`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 int v = (unsigned int)(z - x * _m);if (_m <= v) v += _m;return v;}};// @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 internalnamespace 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 internaltemplate <typename Key, typename Val>struct HashMap {using u32 = uint32_t;using u64 = uint64_t;u32 cap, s;vector<Key> keys;vector<Val> vals;vector<bool> flag;u64 r;u32 shift;Val DefaultValue;static u64 rng() {u64 m = chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();m ^= m >> 16;m ^= m << 32;return m;}void reallocate() {cap <<= 1;vector<Key> k(cap);vector<Val> v(cap);vector<bool> f(cap);u32 sh = shift - 1;for (int i = 0; i < (int)flag.size(); i++) {if (flag[i]) {u32 hash = (u64(keys[i]) * r) >> sh;while (f[hash]) hash = (hash + 1) & (cap - 1);k[hash] = keys[i];v[hash] = vals[i];f[hash] = 1;}}keys.swap(k);vals.swap(v);flag.swap(f);--shift;}explicit HashMap(): cap(8),s(0),keys(cap),vals(cap),flag(cap),r(rng()),shift(64 - __lg(cap)),DefaultValue(Val()) {}Val& operator[](const Key& i) {u32 hash = (u64(i) * r) >> shift;while (true) {if (!flag[hash]) {if (s + s / 4 >= cap) {reallocate();return (*this)[i];}keys[hash] = i;flag[hash] = 1;++s;return vals[hash] = DefaultValue;}if (keys[hash] == i) return vals[hash];hash = (hash + 1) & (cap - 1);}}// exist -> return pointer of Val// not exist -> return nullptrconst Val* find(const Key& i) const {u32 hash = (u64(i) * r) >> shift;while (true) {if (!flag[hash]) return nullptr;if (keys[hash] == i) return &(vals[hash]);hash = (hash + 1) & (cap - 1);}}// return vector< pair<const Key&, val& > >vector<pair<Key, Val>> enumerate() const {vector<pair<Key, Val>> ret;for (u32 i = 0; i < cap; ++i)if (flag[i]) ret.emplace_back(keys[i], vals[i]);return ret;}int size() const { return s; }// set default_valuevoid set_default(const Val& val) { DefaultValue = val; }};template <typename S, typename T>struct DynamicBIT {S N;HashMap<S, T> data;explicit DynamicBIT() = default;explicit DynamicBIT(S size) { N = size + 1; }// explicit DynamicBIT(const vector<S> &A) {// N = A.size() + 1;// for (int i = 0; i < N; i++) add(i, A[i]);// }void add(S k, T x) {for (++k; k < N; k += k & -k) data[k] += x;}void set(S k, T x) {add(k, -get(k) + x);}// [0, k)T sum(S k) const {if (k < 0) return 0;T ret = T();for (; k > 0; k -= k & -k) {const T* p = data.find(k);ret += p ? *p : T();}return ret;}// [a, b)T sum(S a, S b) const { return sum(b) - sum(a); }T get(S k) const { return sum(k + 1) - sum(k); }T operator[](S k) const { return sum(k + 1) - sum(k); }S lower_bound(T w) {if (w <= 0) return 0;S x = 0;for (S k = 1 << __lg(N); k; k >>= 1) {if (x + k <= N - 1 && data[x + k] < w) {w -= data[x + k];x += k;}}return x;}};using S = modint1000000007;signed main() {int N;cin >> N;vector<int> A(N);for (int i = 0; i < N; i++) cin >> A[i];Compress<int> C(A);A = C.zip(A);int len = 0;vector<int> dp(N + 1, INF); // A[i] を末尾とするLISの長さの最大値vector<int> L(N + 1); // 長さiのLISの末尾としてありえる最小値vector<S> cnt(N); // A[i] を末尾とするLISの個数const int ma = C.size() + 1;vector<DynamicBIT<int, S>> bit(N + 1, DynamicBIT<int, S>(ma));for (int i = 0; i < N; i++) { // 2周目int x = lower_bound(L.begin(), L.begin() + len, A[i]) - L.begin();dp[i] = x + 1;L[x] = A[i];if (dp[i] > len) len++;if (dp[i] > 0) {// [x1, x2), [y1, y2)cnt[i] += bit[dp[i] - 1].sum(0, A[i]);}if (cnt[i].val() == 0) cnt[i] = 1; // 実際は矩形領域内の総和が0であるかを複数modで確かめる必要ありbit[dp[i]].add(A[i], cnt[i]);}S ans = 0;for (int i = 0; i < N; i++) {if (dp[i] == len) ans += cnt[i];}cout << ans.val() << endl;}