Problem:
D: Increasing Sequence
問題
N
個の数列が存在している。
i
個目の数列は
M_i
個の要素からなる。
i
個目の数列の
j
番目の要素は
A_{ij}
と表す。
i
個目の数列から
1
個
まで
の要素を選び、選んだ要素を元の数列の順番通りに並べた数列を
X
とする。
数列
X
が単調増加
(X_1\lt X_2\lt X_3\lt...)
するように要素を選ぶ。数列
X
をつくる方法が何通りあるか求めたい。答えは大きくなることがあるので
10^9+7
で割った余りを出力してください。
数列自体が同じであっても、異なる位置から選択した要素が含まれる場合は異なる数列であると区別する。
入力形式
N
M_1
A_{11}
A_{12}
...
A_{1M_1}
M_2
A_{21}
A_{22}
...
A_{2M_2}
...
M_N
A_{N1}
A_{N2}
...
A_{NM_N}
制約
1\leq N\leq 10^5
1\leq M_i
1\leq
\(\sum_{i=1}^NM_i\)
\leq 10^5
1\leq A_{ij}\leq 10^9
入力はすべて整数である
出力形式
数列
X
を作る方法が何通りあるか出力せよ。
入力例1
1
2 1 2
出力例1
3
∅,(1),(2)
の3個です。
入力例2
3
1 3
3 2 5 3
2 1 1
出力例2
8

Submitted solutions:

code_snippet: /* -*- coding: utf-8 -*-
 *
 * 3196.cc: Increasing Sequence
 */

#include<cstdio>
#include<vector>
#include<algorithm>
 
using namespace std;

/* constant */

const int MAX_N = 100000;
const int MAX_M = 100000;
const int MOD = 1000000007;

/* typedef */

typedef vector<int> vi;

template<const int MOD>
struct MI {
  int v;
  MI(): v() {}
  MI(int _v): v(_v % MOD) {}
  MI(long long _v): v(_v % MOD) {}

  MI operator+(const MI m) const { return MI(v + m.v); }
  MI operator-(const MI m) const { return MI(v + MOD - m.v); }
  MI operator*(const MI m) const { return MI((long long)v * m.v); }

  MI &operator+=(const MI m) { return (*this = *this + m); }
  MI &operator-=(const MI m) { return (*this = *this - m); }
  MI &operator*=(const MI m) { return (*this = *this * m); }

  bool operator==(const MI m) const { return v == m.v; }
  bool operator!=(const MI m) const { return v != m.v; }

  MI pow(int n) const {  // a^n % MOD
    MI pm = 1, a = *this;
    while (n > 0) {
      if (n & 1) pm *= a;
      a *= a;
      n >>= 1;
    }
    return pm;
  }

  MI inv() const { return pow(MOD - 2); }
  MI operator/(const MI m) const { return *this * m.inv(); }
  MI &operator/=(const MI m) { return (*this = *this / m); }
};

typedef MI<MOD> mi;

template <typename T>
struct BIT {
  int n;
  vector<T> bits;
  
  BIT() {}
  BIT(int _n) { init(_n); }

  void init(int _n) {
    n = _n;
    bits.assign(n + 1, 0);
  }

  T sum(int x) {
    x = min(x, n);
    T s = 0;
    while (x > 0) {
      s += bits[x];
      x -= (x & -x);
    }
    return s;
  }

  void add(int x, T v) {
    if (x <= 0) return;
    while (x <= n) {
      bits[x] += v;
      x += (x & -x);
    }
  }

  int lower_bound(T v) {
    int	k = 1;
    while ((k << 1) <= n) k <<=	1;
    int	x = 0;
    for	(; k > 0; k >>= 1)
      if (x + k <= n && bits[x + k] < v) {
        x += k;
        v -= bits[x];
      }
    return x + 1;
  }
};

/* global variables */

vi avs[MAX_N];
int uas[MAX_M + 1], ks[MAX_M], ts[MAX_M];
BIT<mi> bit;

/* subroutines */

/* main */

int main() {
  int n;
  scanf("%d", &n);

  int m = 0;
  uas[m++] = 0;
  for (int i = 0; i < n; i++) {
    int mi;
    scanf("%d", &mi);
    avs[i].resize(mi);
    for (int j = 0; j < mi; j++)
      scanf("%d", &avs[i][j]), uas[m++] = avs[i][j];
    sort(avs[i].begin(), avs[i].end());
  }

  sort(uas, uas + m);
  m = unique(uas, uas + m) - uas;

  bit.init(m);
  bit.add(1, 1);

  for (int i = 0; i < n; i++) {
    int mi = avs[i].size();
    for (int j = 0; j < mi; j++) {
      ks[j] = lower_bound(uas, uas + m, avs[i][j]) - uas;
      ts[j] = bit.sum(ks[j]).v;
    }

    for (int j = 0; j < mi; j++) bit.add(ks[j] + 1, ts[j]);
  }

  printf("%d\n", bit.sum(m).v);
  return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 7412
final_rank: 1

code_snippet: #ifdef LOCAL
    #define _GLIBCXX_DEBUG
    #define __clock__
#else
    #pragma GCC optimize("Ofast")
#endif
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using VI = vector<ll>;
using VV = vector<VI>;
using VS = vector<string>;
using PII = pair<ll, ll>;

// #define INT128 // 必要なら有効化してください
#ifdef INT128
  using LL = __int128;
#endif

// tourist set
template <typename A, typename B>
string to_string(pair<A, B> p);

template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p);

template <typename A, typename B, typename C, typename D>
string to_string(tuple<A, B, C, D> p);

string to_string(const string& s) {
  return '"' + s + '"';
}

string to_string(const char* s) {
  return to_string((string) s);
}

string to_string(bool b) {
  return (b ? "true" : "false");
}

string to_string(char c){
  string s = {c};
  return s;
}

// LL
#ifdef INT128
// input
istream& operator>>(istream& is, LL& v)
{
    string s;
    is >> s;
    v = 0;
    for (int i = 0; i < (int)s.size(); i++) {
        if (isdigit(s[i])) { v = v * 10 + s[i] - '0'; }
    }
    if (s[0] == '-') { v *= -1; }
    return is;
}
std::ostream &operator<<(std::ostream &dest, LL value) {
  std::ostream::sentry s(dest);
  if (s) {
    LL tmp = value < 0 ? -value : value;
    char buffer[128];
    char *d = std::end(buffer);
    do {
      --d;
      *d = "0123456789"[tmp % 10];
      tmp /= 10;
    } while (tmp != 0);
    if (value < 0) {
      --d;
      *d = '-';
    }
    int len = std::end(buffer) - d;
    if (dest.rdbuf()->sputn(d, len) != len) {
      dest.setstate(std::ios_base::badbit);
    }
  }
  return dest;
}
string to_string(LL v){
  stringstream ss;
  ss << v;
  return ss.str();
}
#endif // LL

string to_string(vector<bool> v) {
  bool first = true;
  string res = "{";
  for (int i = 0; i < static_cast<int>(v.size()); i++) {
    if (!first) {
      res += ", ";
    }
    first = false;
    res += to_string(v[i]);
  }
  res += "}";
  return res;
}

template <size_t N>
string to_string(bitset<N> v) {
  string res = "";
  for (size_t i = 0; i < N; i++) {
    res += static_cast<char>('0' + v[i]);
  }
  return res;
}

template <typename A>
string to_string(A v) {
  bool first = true;
  string res = "{";
  for (const auto &x : v) {
    if (!first) {
      res += ", ";
    }
    first = false;
    res += to_string(x);
  }
  res += "}";
  return res;
}

template <typename A, typename B>
string to_string(pair<A, B> p) {
  return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}

template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p) {
  return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ")";
}

template <typename A, typename B, typename C, typename D>
string to_string(tuple<A, B, C, D> p) {
  return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ", " + to_string(get<3>(p)) + ")";
}

void debug_out() { cerr << '\n'; }

template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
  cerr << " " << to_string(H);
  debug_out(T...);
}

#ifdef LOCAL
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif
// tourist set end

template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }

#define FOR(i,a,b) for(ll i=(a);i<(b);++i)
#define rep(i,b) FOR(i, 0, b)
#define ALL(v) (v).begin(), (v).end()
#define p(s) cout<<(s)<<'\n'
#define p2(s, t) cout << (s) << " " << (t) << '\n'
#define SZ(x) ((int)(x).size())
#define SORT(A) sort(ALL(A))
#define RSORT(A) sort(ALL(A), greater<ll>())
#define MP make_pair
#define p_yes() p("Yes")
#define p_no() p("No")
#define p_possible() p("Possible")
#define p_impossible() p("Impossible")
void yes(){p_yes(); exit(0);}
void no(){p_no(); exit(0);}
void possible(){p_possible(); exit(0);}
void impossible(){p_impossible(); exit(0);}

ll SUM(VI& V){
  return accumulate(ALL(V), 0LL);
}

ll MIN(VI& V){return *min_element(ALL(V));}
ll MAX(VI& V){return *max_element(ALL(V));}

void print_vector(VI& V, ll offset=0){
  ll n = V.size();
  rep(i, n){
    if(i) cout << ' ';
    cout << V[i]+offset;
  }
  cout << endl;
}

ll gcd(ll a,ll b){
    if(b == 0) return a;
    return gcd(b,a%b);
}

ll lcm(ll a,ll b){
    ll g = gcd(a,b);
    return a / g * b;
}

// long double
using ld = long double;
// #define EPS (1e-14)
constexpr ld EPS = 1e-14;
// #define equals(a,b) (fabs((a)-(b)) < EPS)
constexpr bool equals(ld a, ld b){return fabs((a)-(b)) < EPS;}

// 小さい順に取り出すpriority queue
using inverse_priority_queue = priority_queue<ll, vector<ll>, greater<ll> >;

int popcount(ll t){
    return __builtin_popcountll(t);
}

const ll mod = 1e9 + 7;
// const ll mod = 998244353;
const ll inf = 4e18; // LLONG_MAX = 9223372036854775807 (atcoder, codeforces)
const double PI = acos(-1);

// [a/b] (繰り上げ)
ll ceil_div(ll a, ll b){
  return (a+b-1)/b;
}

ll ll_pow(ll a, ll n){
    ll ans = 1;
    FOR(i, 0, n){
        ans *= a;
    }
    return ans;
}
// modなし

// snuke's mint
// auto mod int
// https://youtu.be/L8grWxBlIZ4?t=9858
// https://youtu.be/ERZuLAxZffQ?t=4807 : optimize
// https://youtu.be/8uowVvQ_-Mo?t=1329 : division
// const int mod = 1000000007;
struct mint {
  ll x; // using ll = long long;
  mint(ll x=0):x((x%mod+mod)%mod){}
  mint operator-() const { return mint(-x);}
  mint& operator+=(const mint a) {
    if ((x += a.x) >= mod) x -= mod;
    return *this;
  }
  mint& operator-=(const mint a) {
    if ((x += mod-a.x) >= mod) x -= mod;
    return *this;
  }
  mint& operator*=(const mint a) {
    (x *= a.x) %= mod;
    return *this;
  }
  mint operator+(const mint a) const {
    mint res(*this);
    return res+=a;
  }
  mint operator-(const mint a) const {
    mint res(*this);
    return res-=a;
  }
  mint operator*(const mint a) const {
    mint res(*this);
    return res*=a;
  }
  mint pow(ll t) const {
    if (!t) return 1;
    mint a = pow(t>>1);
    a *= a;
    if (t&1) a *= *this;
    return a;
  }

  // for prime mod
  mint inv() const {
    return pow(mod-2);
  }
  mint& operator/=(const mint a) {
    return (*this) *= a.inv();
  }
  mint operator/(const mint a) const {
    mint res(*this);
    return res/=a;
  }
};

// ※双方向
// N : 頂点数
// M : 辺数
// return vector<vector<ll>>
VV load_graph(ll N, ll M){
  VV G(N);
  rep(i,M){
    ll a,b;cin>>a>>b;
    a--;b--;
    G[a].push_back(b);
    G[b].push_back(a);
  }
  return G;
}
VV load_tree(ll N){
  return load_graph(N, N-1);
}

VI loadV(ll N){
  VI A(N);
  rep(i,N)cin>>A[i];
  return A;
}

//#include <atcoder/dsu>
//using namespace atcoder; // 忘れがち

// 座標圧縮
// 変換テーブルを返す
VI make_compress_table(vector<ll>& A){  
  // 変換表
  auto B = A;
  sort(ALL(B));
  auto it = unique(ALL(B));
  B.erase(it, B.end());
  return B;
}
ll compress_by_table(VI& T, ll v){
  return lower_bound(ALL(T), v) - T.begin();
}

template< typename T >
struct BinaryIndexedTree {
  vector< T > data;
 
  BinaryIndexedTree(int sz) {
    data.assign(++sz, 0);
  }
 
  T sum(int k) {
    T ret = 0;
    for(++k; k > 0; k -= k & -k) ret += data[k];
    return (ret);
  }
 
  // [i, j]
  mint range_sum(ll i, ll j){
    if(i==0){
      return sum(j);
    }else{
      return sum(j) - sum(i-1);    
    }
  }
 
  void add(int k, T x) {
    for(++k; k < data.size(); k += k & -k) data[k] += x;
  }
};

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);

    // input
    ll N;
    cin>>N;
    
    VV A(N);
    rep(i,N){
      ll n;cin>>n;
      A[i] = loadV(n);
    }

    VI tbl;
    {
      VI all = {0};
      rep(i,N){
        for(ll a : A[i])all.push_back(a);
      }
      tbl = make_compress_table(all);
    }
    // 座圧
    ll ma=0;
    rep(i,N){
      rep(j,SZ(A[i])){
        A[i][j] = compress_by_table(tbl, A[i][j]);
      }
      RSORT(A[i]);
      debug(A[i]);
      chmax(ma,A[i][0]);
    }

    BinaryIndexedTree<mint> bit(ma+1);
    bit.add(0,1);
    rep(i,N){
      for(ll a : A[i]){
        mint m = bit.range_sum(0,a-1);
        bit.add(a,m);
      }
    }

    mint ans = bit.range_sum(0,ma);
    p(ans.x);
    
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 7740
final_rank: 2

code_snippet: #include <bits/stdc++.h>
//#include <atcoder/all>
//using namespace atcoder;
#pragma GCC target ("avx2")
#pragma GCC optimization ("O3")
#pragma GCC optimization ("unroll-loops")

using namespace std;

typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef pair<int, int> PII;
typedef pair<int, int> pii;
typedef pair<long long, long long> PLL;
typedef pair<int, PII> TIII;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;


#define FOR(i, s, n) for (int i = s; i < (int)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define rep(i, a, b) for (int i = a; i < (b); ++i)
#define trav(a, x) for (auto &a : x)
#define all(x) x.begin(), x.end()

#define MOD 1000000007

template<class T1, class T2> inline bool chmax(T1 &a, T2 b) {if (a < b) {a = b; return true;} return false;}
template<class T1, class T2> inline bool chmin(T1 &a, T2 b) {if (a > b) {a = b; return true;} return false;}
const double EPS = 1e-9, PI = acos(-1);
const double pi = 3.141592653589793238462643383279;
//ここから編集    
typedef string::const_iterator State;
ll GCD(ll a, ll b){
  return (b==0)?a:GCD(b, a%b);
}
ll LCM(ll a, ll b){
  return a/GCD(a, b) * b;
}
template< int mod >
struct ModInt {
  int x;

  ModInt() : x(0) {}

  ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}

  ModInt &operator+=(const ModInt &p) {
    if((x += p.x) >= mod) x -= mod;
    return *this;
  }

  ModInt &operator-=(const ModInt &p) {
    if((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }

  ModInt &operator*=(const ModInt &p) {
    x = (int) (1LL * x * p.x % mod);
    return *this;
  }

  ModInt &operator/=(const ModInt &p) {
    *this *= p.inverse();
    return *this;
  }

  ModInt operator-() const { return ModInt(-x); }

  ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }

  ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }

  ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }

  ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }

  bool operator==(const ModInt &p) const { return x == p.x; }

  bool operator!=(const ModInt &p) const { return x != p.x; }

  ModInt inverse() const {
    int a = x, b = mod, u = 1, v = 0, t;
    while(b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }

  ModInt pow(int64_t n) const {
    ModInt ret(1), mul(x);
    while(n > 0) {
      if(n & 1) ret *= mul;
      mul *= mul;
      n >>= 1;
    }
    return ret;
  }

  friend ostream &operator<<(ostream &os, const ModInt &p) {
    return os << p.x;
  }

  friend istream &operator>>(istream &is, ModInt &a) {
    int64_t t;
    is >> t;
    a = ModInt< mod >(t);
    return (is);
  }

  static int get_mod() { return mod; }
};

using modint = ModInt< 1000000007 >;
template< typename T >
struct Combination {
  vector< T > _fact, _rfact, _inv;

  Combination(int sz) : _fact(sz + 1), _rfact(sz + 1), _inv(sz + 1) {
    _fact[0] = _rfact[sz] = _inv[0] = 1;
    for(int i = 1; i <= sz; i++) _fact[i] = _fact[i - 1] * i;
    _rfact[sz] /= _fact[sz];
    for(int i = sz - 1; i >= 0; i--) _rfact[i] = _rfact[i + 1] * (i + 1);
    for(int i = 1; i <= sz; i++) _inv[i] = _rfact[i] * _fact[i - 1];
  }

  inline T fact(int k) const { return _fact[k]; }

  inline T rfact(int k) const { return _rfact[k]; }

  inline T inv(int k) const { return _inv[k]; }

  T P(int n, int r) const {
    if(r < 0 || n < r) return 0;
    return fact(n) * rfact(n - r);
  }

  T C(int p, int q) const {
    if(q < 0 || p < q) return 0;
    return fact(p) * rfact(q) * rfact(p - q);
  }

  T H(int n, int r) const {
    if(n < 0 || r < 0) return (0);
    return r == 0 ? 1 : C(n + r - 1, r);
  }
};
template<typename T = int> struct BIT{
  vector<T> node;
 
  int N;
  BIT(int n){
    N = n;
    node.resize(N+1);
  }
  void add(int i, T x){
    i++;
    while(i <= N){
      node[i] += x;
      i += (i & -i);
    }
  }
  T sum(int i){
    T res = 0;
    while(i > 0){
      res += node[i];
      i -= (i & -i);
    }
    return res;
  }
};
int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(12);
  
  int N; cin >> N;
  vector<int> v;
  vector<vector<int>> a(N);
  v.push_back(0);
  REP(i,N){
    int M; cin >> M;
    a[i].resize(M);
    REP(j,M) cin >> a[i][j];
    REP(j,M) v.push_back(a[i][j]);
  }
  sort(all(v));
  v.erase(unique(all(v)), v.end());

  REP(i,N){
    REP(j,a[i].size()) a[i][j] = lower_bound(all(v), a[i][j]) - v.begin();
  }

  BIT<modint> bit(v.size()+10);

  bit.add(0, 1);
  REP(i,N){
    sort(all(a[i]));
    reverse(all(a[i]));
    REP(j,a[i].size()){
      modint tmp = bit.sum(a[i][j]);
      bit.add(a[i][j], tmp);
    }
  }
  
  cout << bit.sum(v.size()+5) <<  endl;
  return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 6532
final_rank: 3

code_snippet: #line 2 "/home/yuruhiya/programming/library/template/template_no_Ruby.cpp"
#include <bits/stdc++.h>
#line 4 "/home/yuruhiya/programming/library/template/constants.cpp"
#include <string_view>
#line 7 "/home/yuruhiya/programming/library/template/constants.cpp"

#define rep(i, n) for (int i = 0; i < (n); ++i)
#define FOR(i, m, n) for (int i = (m); i < (n); ++i)
#define rrep(i, n) for (int i = (n)-1; i >= 0; --i)
#define rfor(i, m, n) for (int i = (m); i >= (n); --i)
#define unless(c) if (!(c))
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define range_it(a, l, r) (a).begin() + (l), (a).begin() + (r)

using namespace std;
using ll = long long;
using LD = long double;
using VB = vector<bool>;
using VVB = vector<VB>;
using VI = vector<int>;
using VVI = vector<VI>;
using VL = vector<ll>;
using VVL = vector<VL>;
using VS = vector<string>;
using VD = vector<LD>;
using PII = pair<int, int>;
using VP = vector<PII>;
using PLL = pair<ll, ll>;
using VPL = vector<PLL>;
template <class T> using PQ = priority_queue<T>;
template <class T> using PQS = priority_queue<T, vector<T>, greater<T>>;
constexpr int inf = 1000000000;
constexpr long long inf_ll = 1000000000000000000ll, MOD = 1000000007;
constexpr long double PI = 3.14159265358979323846, EPS = 1e-12;
namespace CharacterClass {
	constexpr string_view
	    digit = "0123456789",
	    xdigit = "0123456789ABCDEFabcdef", lower = "abcdefghijklmnopqrstuvwxyz",
	    upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
	    alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
	    alnum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
	    word = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz",
	    punct = R"(!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~)",
	    graph =
	        R"(!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~)",
	    print =
	        R"( !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~)",
	    blank = " \t", space = " \t\n\r\f\v";
}  // namespace CharacterClass
#line 7 "/home/yuruhiya/programming/library/template/Input.cpp"
using namespace std;

#ifdef _WIN32
#define getchar_unlocked _getchar_nolock
#define putchar_unlocked _putchar_nolock
#define fwrite_unlocked fwrite
#define fflush_unlocked fflush
#endif
class Scanner {
	static int gc() {
		return getchar_unlocked();
	}
	static char next_char() {
		char c;
		read(c);
		return c;
	}
	template <class T> static void read(T& v) {
		cin >> v;
	}
	static void read(char& v) {
		while (isspace(v = gc()))
			;
	}
	static void read(bool& v) {
		v = next_char() != '0';
	}
	static void read(string& v) {
		v.clear();
		for (char c = next_char(); !isspace(c); c = gc()) v += c;
	}
	static void read(int& v) {
		v = 0;
		bool neg = false;
		char c = next_char();
		if (c == '-') {
			neg = true;
			c = gc();
		}
		for (; isdigit(c); c = gc()) v = v * 10 + (c - '0');
		if (neg) v = -v;
	}
	static void read(long long& v) {
		v = 0;
		bool neg = false;
		char c = next_char();
		if (c == '-') {
			neg = true;
			c = gc();
		}
		for (; isdigit(c); c = gc()) v = v * 10 + (c - '0');
		if (neg) v = -v;
	}
	static void read(double& v) {
		v = 0;
		double dp = 1;
		bool neg = false, after_dp = false;
		char c = next_char();
		if (c == '-') {
			neg = true;
			c = gc();
		}
		for (; isdigit(c) || c == '.'; c = gc()) {
			if (c == '.') {
				after_dp = true;
			} else if (after_dp) {
				v += (c - '0') * (dp *= 0.1);
			} else {
				v = v * 10 + (c - '0');
			}
		}
		if (neg) v = -v;
	}
	static void read(long double& v) {
		v = 0;
		long double dp = 1;
		bool neg = false, after_dp = false;
		char c = next_char();
		if (c == '-') {
			neg = true;
			c = gc();
		}
		for (; isdigit(c) || c == '.'; c = gc()) {
			if (c == '.') {
				after_dp = true;
			} else if (after_dp) {
				v += (c - '0') * (dp *= 0.1);
			} else {
				v = v * 10 + (c - '0');
			}
		}
		if (neg) v = -v;
	}
	template <class T, class U> static void read(pair<T, U>& v) {
		read(v.first);
		read(v.second);
	}
	template <class T> static void read(vector<T>& v) {
		for (auto& e : v) read(e);
	}
	template <size_t N = 0, class T> static void read_tuple_impl(T& v) {
		if constexpr (N < tuple_size_v<T>) {
			read(get<N>(v));
			read_tuple_impl<N + 1>(v);
		}
	}
	template <class... T> static void read(tuple<T...>& v) {
		read_tuple_impl(v);
	}
	struct ReadVectorHelper {
		size_t n;
		ReadVectorHelper(size_t _n) : n(_n) {}
		template <class T> operator vector<T>() {
			vector<T> v(n);
			read(v);
			return v;
		}
	};
	struct Read2DVectorHelper {
		size_t n, m;
		Read2DVectorHelper(const pair<size_t, size_t>& nm) : n(nm.first), m(nm.second) {}
		template <class T> operator vector<vector<T>>() {
			vector<vector<T>> v(n, vector<T>(m));
			read(v);
			return v;
		}
	};

public:
	string read_line() const {
		string v;
		for (char c = gc(); c != '\n' && c != '\0'; c = gc()) v += c;
		return v;
	}
	template <class T> T read() const {
		T v;
		read(v);
		return v;
	}
	template <class T> vector<T> read_vector(size_t n) const {
		vector<T> a(n);
		read(a);
		return a;
	}
	template <class T> operator T() const {
		return read<T>();
	}
	int operator--(int) const {
		return read<int>() - 1;
	}
	ReadVectorHelper operator[](size_t n) const {
		return ReadVectorHelper(n);
	}
	Read2DVectorHelper operator[](const pair<size_t, size_t>& nm) const {
		return Read2DVectorHelper(nm);
	}
	void operator()() const {}
	template <class H, class... T> void operator()(H&& h, T&&... t) const {
		read(h);
		operator()(forward<T>(t)...);
	}

private:
	template <template <class...> class, class...> struct Multiple;
	template <template <class...> class V, class Head, class... Tail>
	struct Multiple<V, Head, Tail...> {
		template <class... Args> using vec = V<vector<Head>, Args...>;
		using type = typename Multiple<vec, Tail...>::type;
	};
	template <template <class...> class V> struct Multiple<V> { using type = V<>; };
	template <class... T> using multiple_t = typename Multiple<tuple, T...>::type;
	template <size_t N = 0, class T> void multiple_impl(T& t) const {
		if constexpr (N < tuple_size_v<T>) {
			auto& vec = get<N>(t);
			using V = typename remove_reference_t<decltype(vec)>::value_type;
			vec.push_back(read<V>());
			multiple_impl<N + 1>(t);
		}
	}

public:
	template <class... T> auto multiple(size_t h) const {
		multiple_t<T...> result;
		while (h--) multiple_impl(result);
		return result;
	}
} in;
#define inputs(T, ...) \
	T __VA_ARGS__;     \
	in(__VA_ARGS__)
#define ini(...) inputs(int, __VA_ARGS__)
#define inl(...) inputs(long long, __VA_ARGS__)
#define ins(...) inputs(string, __VA_ARGS__)
#line 7 "/home/yuruhiya/programming/library/template/Output.cpp"
#include <charconv>
#line 10 "/home/yuruhiya/programming/library/template/Output.cpp"
using namespace std;

struct BoolStr {
	const char *t, *f;
	BoolStr(const char* _t, const char* _f) : t(_t), f(_f) {}
} Yes("Yes", "No"), yes("yes", "no"), YES("YES", "NO"), Int("1", "0");
struct DivStr {
	const char *d, *l;
	DivStr(const char* _d, const char* _l) : d(_d), l(_l) {}
} spc(" ", "\n"), no_spc("", "\n"), end_line("\n", "\n"), comma(",", "\n"),
    no_endl(" ", "");
class Printer {
	BoolStr B{Yes};
	DivStr D{spc};

public:
	void print(int v) const {
		char buf[12]{};
		if (auto [ptr, e] = to_chars(begin(buf), end(buf), v); e == errc{}) {
			fwrite(buf, sizeof(char), ptr - buf, stdout);
		} else {
			assert(false);
		}
	}
	void print(long long v) const {
		char buf[21]{};
		if (auto [ptr, e] = to_chars(begin(buf), end(buf), v); e == errc{}) {
			fwrite(buf, sizeof(char), ptr - buf, stdout);
		} else {
			assert(false);
		}
	}
	void print(bool v) const {
		print(v ? B.t : B.f);
	}
	void print(vector<bool>::reference v) const {
		print(v ? B.t : B.f);
	}
	void print(char v) const {
		putchar_unlocked(v);
	}
	void print(const char* v) const {
		fwrite_unlocked(v, 1, strlen(v), stdout);
	}
	void print(double v) const {
		printf("%.20f", v);
	}
	void print(long double v) const {
		printf("%.20Lf", v);
	}
	template <class T> void print(const T& v) const {
		cout << v;
	}
	template <class T, class U> void print(const pair<T, U>& v) const {
		print(v.first);
		print(D.d);
		print(v.second);
	}
	template <class InputIterater>
	void print_range(const InputIterater& begin, const InputIterater& end) const {
		for (InputIterater i = begin; i != end; ++i) {
			if (i != begin) print(D.d);
			print(*i);
		}
	}
	template <class T> void print(const vector<T>& v) const {
		print_range(v.begin(), v.end());
	}
	template <class T, size_t N> void print(const array<T, N>& v) const {
		print_range(v.begin(), v.end());
	}
	template <class T> void print(const vector<vector<T>>& v) const {
		for (size_t i = 0; i < v.size(); ++i) {
			if (i) print(D.l);
			print(v[i]);
		}
	}

	Printer() = default;
	Printer(const BoolStr& _boolstr, const DivStr& _divstr) : B(_boolstr), D(_divstr) {}
	Printer& operator()() {
		print(D.l);
		return *this;
	}
	template <class H> Printer& operator()(H&& h) {
		print(h);
		print(D.l);
		return *this;
	}
	template <class H, class... T> Printer& operator()(H&& h, T&&... t) {
		print(h);
		print(D.d);
		return operator()(forward<T>(t)...);
	}
	template <class InputIterator>
	Printer& range(const InputIterator& begin, const InputIterator& end) {
		print_range(begin, end);
		print(D.l);
		return *this;
	}
	template <class T> Printer& range(const T& a) {
		range(a.begin(), a.end());
		return *this;
	}
	template <class... T> void exit(T&&... t) {
		operator()(forward<T>(t)...);
		std::exit(EXIT_SUCCESS);
	}
	Printer& flush() {
		fflush_unlocked(stdout);
		return *this;
	}
	Printer& set(const BoolStr& b) {
		B = b;
		return *this;
	}
	Printer& set(const DivStr& d) {
		D = d;
		return *this;
	}
	Printer& set(const char* t, const char* f) {
		B = BoolStr(t, f);
		return *this;
	}
} out;
#line 7 "/home/yuruhiya/programming/library/template/functions.cpp"
using namespace std;

template <class T = long long> constexpr T TEN(size_t n) {
	T result = 1;
	for (size_t i = 0; i < n; ++i) result *= 10;
	return result;
}
template <class T, class U,
          enable_if_t<is_integral_v<T> && is_integral_v<U>, nullptr_t> = nullptr>
constexpr auto div_ceil(T n, U m) {
	return (n + m - 1) / m;
}
template <class T, class U> constexpr auto div_ceil2(T n, U m) {
	return div_ceil(n, m) * m;
}
template <class T> constexpr T triangle(T n) {
	return (n & 1) ? (n + 1) / 2 * n : n / 2 * (n + 1);
}
template <class T> constexpr T nC2(T n) {
	return (n & 1) ? (n - 1) / 2 * n : n / 2 * (n - 1);
}
template <class T, class U> constexpr auto middle(const T& l, const U& r) {
	return l + (r - l) / 2;
}
template <class T, class U, class V>
constexpr bool in_range(const T& v, const U& lower, const V& upper) {
	return lower <= v && v < upper;
}
template <class T, enable_if_t<is_integral_v<T>, nullptr_t> = nullptr>
constexpr bool is_square(T n) {
	T s = sqrt(n);
	return s * s == n || (s + 1) * (s + 1) == n;
}
template <class T = long long> constexpr T BIT(int b) {
	return T(1) << b;
}
template <class T> constexpr int BIT(T x, int i) {
	return (x & (T(1) << i)) ? 1 : 0;
}
template <class T, class U, enable_if_t<is_integral_v<U>, nullptr_t> = nullptr>
constexpr T Pow(T a, U n) {
	assert(n >= 0);
	T result = 1;
	while (n > 0) {
		if (n & 1) {
			result *= a;
			n--;
		} else {
			a *= a;
			n >>= 1;
		}
	}
	return result;
}
template <class T, class U, enable_if_t<is_integral_v<U>, nullptr_t> = nullptr>
constexpr T Powmod(T a, U n, T mod) {
	assert(n >= 0);
	if (a > mod) a %= mod;
	T result = 1;
	while (n > 0) {
		if (n & 1) {
			result = result * a % mod;
			n--;
		} else {
			a = a * a % mod;
			n >>= 1;
		}
	}
	return result;
}
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> int sz(const T& v) {
	return v.size();
}
template <class T, class U> int lower_index(const T& a, const U& v) {
	return lower_bound(all(a), v) - a.begin();
}
template <class T, class U> int upper_index(const T& a, const U& v) {
	return upper_bound(all(a), v) - a.begin();
}
template <class T> auto Slice(const T& v, size_t i, size_t len) {
	return i < v.size() ? T(v.begin() + i, v.begin() + min(i + len, v.size())) : T();
}
template <class T, class U = typename T::value_type> U Gcdv(const T& v) {
	return accumulate(next(v.begin()), v.end(), U(*v.begin()), gcd<U, U>);
}
template <class T, class U = typename T::value_type> U Lcmv(const T& v) {
	return accumulate(next(v.begin()), v.end(), U(*v.begin()), lcm<U, U>);
}
namespace internal {
	template <class T, size_t N> auto make_vector(vector<int>& sizes, const T& init) {
		if constexpr (N == 1) {
			return vector(sizes[0], init);
		} else {
			int size = sizes[N - 1];
			sizes.pop_back();
			return vector(size, make_vector<T, N - 1>(sizes, init));
		}
	}
}  // namespace internal
template <class T, size_t N>
auto make_vector(const int (&sizes)[N], const T& init = T()) {
	vector s(rbegin(sizes), rend(sizes));
	return internal::make_vector<T, N>(s, init);
}
#line 7 "/home/yuruhiya/programming/library/template/template_no_Ruby.cpp"
#if __has_include(<library/dump.hpp>)
#include <library/dump.hpp>
#define LOCAL
#else
#define dump(...) ((void)0)
#endif

template <class T> constexpr T oj_local(const T& oj, const T& local) {
#ifndef LOCAL
	return oj;
#else
	return local;
#endif
}
#line 3 "/home/yuruhiya/programming/library/Utility/CulSum.cpp"
#include <type_traits>
#line 5 "/home/yuruhiya/programming/library/Utility/CulSum.cpp"
using namespace std;

template <class T> class CulSum {
public:
	using value_type = T;
	using data_type = vector<value_type>;

private:
	size_t n;
	data_type data;

public:
	CulSum() = default;
	CulSum(const data_type& a) : n(a.size()), data(n + 1) {
		for (size_t i = 0; i < n; ++i) {
			data[i + 1] = data[i] + a[i];
		}
	}
	template <class U, class F, enable_if_t<is_integral_v<U>, nullptr_t> = nullptr>
	CulSum(const U& _n, F f) : n(_n), data(n + 1) {
		for (size_t i = 0; i < n; ++i) {
			data[i + 1] = data[i] + static_cast<value_type>(f(i));
		}
	}
	template <class U, class F, enable_if_t<!is_integral_v<U>, nullptr_t> = nullptr>
	CulSum(const U& a, F f)
	    : CulSum(a.size(), [a, f](size_t i) -> value_type { return f(a[i]); }) {}
	size_t size() const {
		return n;
	}
	value_type at(size_t i) const {
		return operator()(i, i + 1);
	}
	// [l, r)
	value_type operator()(size_t l, size_t r) const {
		l = min(l, n);
		r = min(r, n);
		return l > r ? 0 : data[r] - data[l];
	}
	// [0, r)
	value_type operator()(size_t r) const {
		r = min(r, n);
		return data[r];
	}
	const data_type& get_data() const {
		return data;
	}
};
#line 5 "/home/yuruhiya/programming/library/Math/modint.cpp"
using namespace std;

template <int MOD> struct modint {
	using T = long long;
	T n;
	constexpr modint(const T x = 0) : n(x % MOD) {
		if (n < 0) n += MOD;
	}
	constexpr int get_mod() const {
		return MOD;
	}
	constexpr modint operator+() const {
		return *this;
	}
	constexpr modint operator-() const {
		return n ? MOD - n : 0;
	}
	constexpr modint& operator++() {
		if (MOD <= ++n) n = 0;
		return *this;
	}
	constexpr modint& operator--() {
		if (n <= 0) n = MOD;
		n--;
		return *this;
	}
	constexpr modint operator++(int) {
		modint t = *this;
		++*this;
		return t;
	}
	constexpr modint operator--(int) {
		modint t = *this;
		--*this;
		return t;
	}
	constexpr modint next() const {
		return ++modint(*this);
	}
	constexpr modint pred() const {
		return --modint(*this);
	}
	constexpr modint operator+(const modint& m) const {
		return modint(*this) += m;
	}
	constexpr modint operator-(const modint& m) const {
		return modint(*this) -= m;
	}
	constexpr modint operator*(const modint& m) const {
		return modint(*this) *= m;
	}
	constexpr modint operator/(const modint& m) const {
		return modint(*this) /= m;
	}
	constexpr modint& operator+=(const modint& m) {
		n += m.n;
		if (n >= MOD) n -= MOD;
		return *this;
	}
	constexpr modint& operator-=(const modint& m) {
		n -= m.n;
		if (n < 0) n += MOD;
		return *this;
	}
	constexpr modint& operator*=(const modint& m) {
		n = n * m.n % MOD;
		return *this;
	}
	constexpr modint& operator/=(const modint& m) {
		T a = m.n, b = MOD, u = 1, v = 0;
		while (b) {
			T t = a / b;
			a -= t * b;
			swap(a, b);
			u -= t * v;
			swap(u, v);
		}
		n = n * u % MOD;
		if (n < 0) n += MOD;
		return *this;
	}
	constexpr bool operator==(const modint& m) const {
		return n == m.n;
	}
	constexpr bool operator!=(const modint& m) const {
		return n != m.n;
	}
	template <class M> constexpr modint pow(M m) const {
		if (0 <= m) {
			modint t = n, result = 1;
			while (m > 0) {
				if (m & 1) {
					result *= t;
					m--;
				} else {
					t *= t;
					m >>= 1;
				}
			}
			return result;
		} else {
			return (modint(1) / n).pow(-m);
		}
	}
	template <class M> constexpr modint operator^(M m) const {
		return pow(m);
	}
	friend ostream& operator<<(ostream& os, const modint<MOD>& m) {
		return os << m.n;
	}
	friend istream& operator>>(istream& is, modint<MOD>& m) {
		long long x;
		cin >> x;
		m = modint(x);
		return is;
	}
};
using mint = modint<1000000007>;
using VM = vector<mint>;
mint operator""_m(unsigned long long n) {
	return n;
}
#line 5 "/home/yuruhiya/programming/library/Utility/Compress.cpp"
using namespace std;

template <class T> class Compress {
public:
	using value_type = T;

private:
	vector<value_type> v;
	bool flag = false;

public:
	Compress() {}
	template <class U> Compress(const U& a) {
		add(a);
	}
	Compress& add(const value_type& a) {
		flag = false;
		v.push_back(a);
		return *this;
	}
	template <class U> Compress& add(const vector<U>& a) {
		flag = false;
		for (const auto& i : a) add(i);
		return *this;
	}
	template <class U> Compress& add(const initializer_list<U>& a) {
		flag = false;
		for (const auto& v : a) add(v);
		return *this;
	}
	template <class U> Compress& operator<<(const U& a) {
		add(a);
		return *this;
	}
	void build() {
		sort(v.begin(), v.end());
		v.erase(unique(v.begin(), v.end()), v.end());
		flag = true;
	}
	int operator()(const value_type& x) const {
		assert(flag);
		return lower_bound(v.begin(), v.end(), x) - v.begin();
	}
	vector<int> operator()(const vector<value_type>& x) const {
		assert(flag);
		vector<int> result;
		result.reserve(x.size());
		for (const value_type& i : x) {
			result.push_back(lower_bound(v.begin(), v.end(), i) - v.begin());
		}
		return result;
	}
	int lower(const value_type& x) const {
		assert(flag);
		return lower_bound(v.begin(), v.end(), x) - v.begin();
	}
	int upper(const value_type& x) const {
		assert(flag);
		return upper_bound(v.begin(), v.end(), x) - v.begin();
	}
	int size() const {
		assert(flag);
		return v.size();
	}
	const vector<value_type>& operator*() const {
		assert(flag);
		return v;
	}
	const value_type& operator[](int i) const {
		assert(flag);
		return v[i];
	}
};
#line 1 "/home/yuruhiya/programming/library/atcoder/segtree.hpp"



#line 1 "/home/yuruhiya/programming/library/atcoder/internal_bit.hpp"



#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

	namespace internal {

		// @param n `0 <= n`
		// @return minimum non-negative `x` s.t. `n <= 2**x`
		int ceil_pow2(int n) {
			int x = 0;
			while ((1U << x) < (unsigned int)(n))
				x++;
			return x;
		}

		// @param n `1 <= n`
		// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
		int bsf(unsigned int n) {
#ifdef _MSC_VER
			unsigned long index;
			_BitScanForward(&index, n);
			return index;
#else
			return __builtin_ctz(n);
#endif
		}

	}  // namespace internal

}  // namespace atcoder


#line 8 "/home/yuruhiya/programming/library/atcoder/segtree.hpp"

namespace atcoder {

	template <class S, S (*op)(S, S), S (*e)()> struct segtree {
	public:
		segtree() : segtree(0) {}
		segtree(int n) : segtree(std::vector<S>(n, e())) {}
		segtree(const std::vector<S>& v) : _n(int(v.size())) {
			log = internal::ceil_pow2(_n);
			size = 1 << log;
			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) {
			assert(0 <= p && p < _n);
			return d[p + size];
		}

		S prod(int l, int r) {
			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() {
			return d[1];
		}

		template <bool (*f)(S)> int max_right(int l) {
			return max_right(l, [](S x) {
				return f(x);
			});
		}
		template <class F> int max_right(int l, F f) {
			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) {
			return min_left(r, [](S x) {
				return f(x);
			});
		}
		template <class F> int min_left(int r, F f) {
			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 6 "b.cpp"

mint op(mint a, mint b) {
	return a + b;
}
mint e() {
	return 0_m;
}

int main() {
	ini(n);
	VVI a(n);
	rep(i, n) {
		a[i] = in[in.read<int>()];
		sort(all(a[i]));
	}

	Compress<int> cmp;
	cmp << a << 0;
	cmp.build();

	atcoder::segtree<mint, op, e> seg(cmp.size());
	seg.set(cmp(0), 1);
	rep(i, n) {
		const auto& v = a[i];
		VM memo(v.size());
		rep(j, sz(v)) {
			memo[j] = seg.prod(0, cmp.lower(v[j]));
		}
		rep(j, sz(v)) {
			int k = cmp(v[j]);
			seg.set(k, seg.get(k) + memo[j]);
		}
	}
	out(seg.all_prod());
}
accuracy: 1
time_ms: 30
memory_kb: 9424
final_rank: 5

code_snippet: #line 2 "/home/yuruhiya/programming/library/template/template_no_Ruby.cpp"
#include <bits/stdc++.h>
#line 4 "/home/yuruhiya/programming/library/template/constants.cpp"
#include <string_view>
#line 7 "/home/yuruhiya/programming/library/template/constants.cpp"

#define rep(i, n) for (int i = 0; i < (n); ++i)
#define FOR(i, m, n) for (int i = (m); i < (n); ++i)
#define rrep(i, n) for (int i = (n)-1; i >= 0; --i)
#define rfor(i, m, n) for (int i = (m); i >= (n); --i)
#define unless(c) if (!(c))
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define range_it(a, l, r) (a).begin() + (l), (a).begin() + (r)

using namespace std;
using ll = long long;
using LD = long double;
using VB = vector<bool>;
using VVB = vector<VB>;
using VI = vector<int>;
using VVI = vector<VI>;
using VL = vector<ll>;
using VVL = vector<VL>;
using VS = vector<string>;
using VD = vector<LD>;
using PII = pair<int, int>;
using VP = vector<PII>;
using PLL = pair<ll, ll>;
using VPL = vector<PLL>;
template <class T> using PQ = priority_queue<T>;
template <class T> using PQS = priority_queue<T, vector<T>, greater<T>>;
constexpr int inf = 1000000000;
constexpr long long inf_ll = 1000000000000000000ll, MOD = 1000000007;
constexpr long double PI = 3.14159265358979323846, EPS = 1e-12;
namespace CharacterClass {
	constexpr string_view
	    digit = "0123456789",
	    xdigit = "0123456789ABCDEFabcdef", lower = "abcdefghijklmnopqrstuvwxyz",
	    upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
	    alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
	    alnum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
	    word = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz",
	    punct = R"(!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~)",
	    graph =
	        R"(!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~)",
	    print =
	        R"( !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~)",
	    blank = " \t", space = " \t\n\r\f\v";
}  // namespace CharacterClass
#line 7 "/home/yuruhiya/programming/library/template/Input.cpp"
using namespace std;

#ifdef _WIN32
#define getchar_unlocked _getchar_nolock
#define putchar_unlocked _putchar_nolock
#define fwrite_unlocked fwrite
#define fflush_unlocked fflush
#endif
class Scanner {
	static int gc() {
		return getchar_unlocked();
	}
	static char next_char() {
		char c;
		read(c);
		return c;
	}
	template <class T> static void read(T& v) {
		cin >> v;
	}
	static void read(char& v) {
		while (isspace(v = gc()))
			;
	}
	static void read(bool& v) {
		v = next_char() != '0';
	}
	static void read(string& v) {
		v.clear();
		for (char c = next_char(); !isspace(c); c = gc()) v += c;
	}
	static void read(int& v) {
		v = 0;
		bool neg = false;
		char c = next_char();
		if (c == '-') {
			neg = true;
			c = gc();
		}
		for (; isdigit(c); c = gc()) v = v * 10 + (c - '0');
		if (neg) v = -v;
	}
	static void read(long long& v) {
		v = 0;
		bool neg = false;
		char c = next_char();
		if (c == '-') {
			neg = true;
			c = gc();
		}
		for (; isdigit(c); c = gc()) v = v * 10 + (c - '0');
		if (neg) v = -v;
	}
	static void read(double& v) {
		v = 0;
		double dp = 1;
		bool neg = false, after_dp = false;
		char c = next_char();
		if (c == '-') {
			neg = true;
			c = gc();
		}
		for (; isdigit(c) || c == '.'; c = gc()) {
			if (c == '.') {
				after_dp = true;
			} else if (after_dp) {
				v += (c - '0') * (dp *= 0.1);
			} else {
				v = v * 10 + (c - '0');
			}
		}
		if (neg) v = -v;
	}
	static void read(long double& v) {
		v = 0;
		long double dp = 1;
		bool neg = false, after_dp = false;
		char c = next_char();
		if (c == '-') {
			neg = true;
			c = gc();
		}
		for (; isdigit(c) || c == '.'; c = gc()) {
			if (c == '.') {
				after_dp = true;
			} else if (after_dp) {
				v += (c - '0') * (dp *= 0.1);
			} else {
				v = v * 10 + (c - '0');
			}
		}
		if (neg) v = -v;
	}
	template <class T, class U> static void read(pair<T, U>& v) {
		read(v.first);
		read(v.second);
	}
	template <class T> static void read(vector<T>& v) {
		for (auto& e : v) read(e);
	}
	template <size_t N = 0, class T> static void read_tuple_impl(T& v) {
		if constexpr (N < tuple_size_v<T>) {
			read(get<N>(v));
			read_tuple_impl<N + 1>(v);
		}
	}
	template <class... T> static void read(tuple<T...>& v) {
		read_tuple_impl(v);
	}
	struct ReadVectorHelper {
		size_t n;
		ReadVectorHelper(size_t _n) : n(_n) {}
		template <class T> operator vector<T>() {
			vector<T> v(n);
			read(v);
			return v;
		}
	};
	struct Read2DVectorHelper {
		size_t n, m;
		Read2DVectorHelper(const pair<size_t, size_t>& nm) : n(nm.first), m(nm.second) {}
		template <class T> operator vector<vector<T>>() {
			vector<vector<T>> v(n, vector<T>(m));
			read(v);
			return v;
		}
	};

public:
	string read_line() const {
		string v;
		for (char c = gc(); c != '\n' && c != '\0'; c = gc()) v += c;
		return v;
	}
	template <class T> T read() const {
		T v;
		read(v);
		return v;
	}
	template <class T> vector<T> read_vector(size_t n) const {
		vector<T> a(n);
		read(a);
		return a;
	}
	template <class T> operator T() const {
		return read<T>();
	}
	int operator--(int) const {
		return read<int>() - 1;
	}
	ReadVectorHelper operator[](size_t n) const {
		return ReadVectorHelper(n);
	}
	Read2DVectorHelper operator[](const pair<size_t, size_t>& nm) const {
		return Read2DVectorHelper(nm);
	}
	void operator()() const {}
	template <class H, class... T> void operator()(H&& h, T&&... t) const {
		read(h);
		operator()(forward<T>(t)...);
	}

private:
	template <template <class...> class, class...> struct Multiple;
	template <template <class...> class V, class Head, class... Tail>
	struct Multiple<V, Head, Tail...> {
		template <class... Args> using vec = V<vector<Head>, Args...>;
		using type = typename Multiple<vec, Tail...>::type;
	};
	template <template <class...> class V> struct Multiple<V> { using type = V<>; };
	template <class... T> using multiple_t = typename Multiple<tuple, T...>::type;
	template <size_t N = 0, class T> void multiple_impl(T& t) const {
		if constexpr (N < tuple_size_v<T>) {
			auto& vec = get<N>(t);
			using V = typename remove_reference_t<decltype(vec)>::value_type;
			vec.push_back(read<V>());
			multiple_impl<N + 1>(t);
		}
	}

public:
	template <class... T> auto multiple(size_t h) const {
		multiple_t<T...> result;
		while (h--) multiple_impl(result);
		return result;
	}
} in;
#define inputs(T, ...) \
	T __VA_ARGS__;     \
	in(__VA_ARGS__)
#define ini(...) inputs(int, __VA_ARGS__)
#define inl(...) inputs(long long, __VA_ARGS__)
#define ins(...) inputs(string, __VA_ARGS__)
#line 7 "/home/yuruhiya/programming/library/template/Output.cpp"
#include <charconv>
#line 10 "/home/yuruhiya/programming/library/template/Output.cpp"
using namespace std;

struct BoolStr {
	const char *t, *f;
	BoolStr(const char* _t, const char* _f) : t(_t), f(_f) {}
} Yes("Yes", "No"), yes("yes", "no"), YES("YES", "NO"), Int("1", "0");
struct DivStr {
	const char *d, *l;
	DivStr(const char* _d, const char* _l) : d(_d), l(_l) {}
} spc(" ", "\n"), no_spc("", "\n"), end_line("\n", "\n"), comma(",", "\n"),
    no_endl(" ", "");
class Printer {
	BoolStr B{Yes};
	DivStr D{spc};

public:
	void print(int v) const {
		char buf[12]{};
		if (auto [ptr, e] = to_chars(begin(buf), end(buf), v); e == errc{}) {
			fwrite(buf, sizeof(char), ptr - buf, stdout);
		} else {
			assert(false);
		}
	}
	void print(long long v) const {
		char buf[21]{};
		if (auto [ptr, e] = to_chars(begin(buf), end(buf), v); e == errc{}) {
			fwrite(buf, sizeof(char), ptr - buf, stdout);
		} else {
			assert(false);
		}
	}
	void print(bool v) const {
		print(v ? B.t : B.f);
	}
	void print(vector<bool>::reference v) const {
		print(v ? B.t : B.f);
	}
	void print(char v) const {
		putchar_unlocked(v);
	}
	void print(const char* v) const {
		fwrite_unlocked(v, 1, strlen(v), stdout);
	}
	void print(double v) const {
		printf("%.20f", v);
	}
	void print(long double v) const {
		printf("%.20Lf", v);
	}
	template <class T> void print(const T& v) const {
		cout << v;
	}
	template <class T, class U> void print(const pair<T, U>& v) const {
		print(v.first);
		print(D.d);
		print(v.second);
	}
	template <class InputIterater>
	void print_range(const InputIterater& begin, const InputIterater& end) const {
		for (InputIterater i = begin; i != end; ++i) {
			if (i != begin) print(D.d);
			print(*i);
		}
	}
	template <class T> void print(const vector<T>& v) const {
		print_range(v.begin(), v.end());
	}
	template <class T, size_t N> void print(const array<T, N>& v) const {
		print_range(v.begin(), v.end());
	}
	template <class T> void print(const vector<vector<T>>& v) const {
		for (size_t i = 0; i < v.size(); ++i) {
			if (i) print(D.l);
			print(v[i]);
		}
	}

	Printer() = default;
	Printer(const BoolStr& _boolstr, const DivStr& _divstr) : B(_boolstr), D(_divstr) {}
	Printer& operator()() {
		print(D.l);
		return *this;
	}
	template <class H> Printer& operator()(H&& h) {
		print(h);
		print(D.l);
		return *this;
	}
	template <class H, class... T> Printer& operator()(H&& h, T&&... t) {
		print(h);
		print(D.d);
		return operator()(forward<T>(t)...);
	}
	template <class InputIterator>
	Printer& range(const InputIterator& begin, const InputIterator& end) {
		print_range(begin, end);
		print(D.l);
		return *this;
	}
	template <class T> Printer& range(const T& a) {
		range(a.begin(), a.end());
		return *this;
	}
	template <class... T> void exit(T&&... t) {
		operator()(forward<T>(t)...);
		std::exit(EXIT_SUCCESS);
	}
	Printer& flush() {
		fflush_unlocked(stdout);
		return *this;
	}
	Printer& set(const BoolStr& b) {
		B = b;
		return *this;
	}
	Printer& set(const DivStr& d) {
		D = d;
		return *this;
	}
	Printer& set(const char* t, const char* f) {
		B = BoolStr(t, f);
		return *this;
	}
} out;
#line 7 "/home/yuruhiya/programming/library/template/functions.cpp"
using namespace std;

template <class T = long long> constexpr T TEN(size_t n) {
	T result = 1;
	for (size_t i = 0; i < n; ++i) result *= 10;
	return result;
}
template <class T, class U,
          enable_if_t<is_integral_v<T> && is_integral_v<U>, nullptr_t> = nullptr>
constexpr auto div_ceil(T n, U m) {
	return (n + m - 1) / m;
}
template <class T, class U> constexpr auto div_ceil2(T n, U m) {
	return div_ceil(n, m) * m;
}
template <class T> constexpr T triangle(T n) {
	return (n & 1) ? (n + 1) / 2 * n : n / 2 * (n + 1);
}
template <class T> constexpr T nC2(T n) {
	return (n & 1) ? (n - 1) / 2 * n : n / 2 * (n - 1);
}
template <class T, class U> constexpr auto middle(const T& l, const U& r) {
	return l + (r - l) / 2;
}
template <class T, class U, class V>
constexpr bool in_range(const T& v, const U& lower, const V& upper) {
	return lower <= v && v < upper;
}
template <class T, enable_if_t<is_integral_v<T>, nullptr_t> = nullptr>
constexpr bool is_square(T n) {
	T s = sqrt(n);
	return s * s == n || (s + 1) * (s + 1) == n;
}
template <class T = long long> constexpr T BIT(int b) {
	return T(1) << b;
}
template <class T> constexpr int BIT(T x, int i) {
	return (x & (T(1) << i)) ? 1 : 0;
}
template <class T, class U, enable_if_t<is_integral_v<U>, nullptr_t> = nullptr>
constexpr T Pow(T a, U n) {
	assert(n >= 0);
	T result = 1;
	while (n > 0) {
		if (n & 1) {
			result *= a;
			n--;
		} else {
			a *= a;
			n >>= 1;
		}
	}
	return result;
}
template <class T, class U, enable_if_t<is_integral_v<U>, nullptr_t> = nullptr>
constexpr T Powmod(T a, U n, T mod) {
	assert(n >= 0);
	if (a > mod) a %= mod;
	T result = 1;
	while (n > 0) {
		if (n & 1) {
			result = result * a % mod;
			n--;
		} else {
			a = a * a % mod;
			n >>= 1;
		}
	}
	return result;
}
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> int sz(const T& v) {
	return v.size();
}
template <class T, class U> int lower_index(const T& a, const U& v) {
	return lower_bound(all(a), v) - a.begin();
}
template <class T, class U> int upper_index(const T& a, const U& v) {
	return upper_bound(all(a), v) - a.begin();
}
template <class T> auto Slice(const T& v, size_t i, size_t len) {
	return i < v.size() ? T(v.begin() + i, v.begin() + min(i + len, v.size())) : T();
}
template <class T, class U = typename T::value_type> U Gcdv(const T& v) {
	return accumulate(next(v.begin()), v.end(), U(*v.begin()), gcd<U, U>);
}
template <class T, class U = typename T::value_type> U Lcmv(const T& v) {
	return accumulate(next(v.begin()), v.end(), U(*v.begin()), lcm<U, U>);
}
namespace internal {
	template <class T, size_t N> auto make_vector(vector<int>& sizes, const T& init) {
		if constexpr (N == 1) {
			return vector(sizes[0], init);
		} else {
			int size = sizes[N - 1];
			sizes.pop_back();
			return vector(size, make_vector<T, N - 1>(sizes, init));
		}
	}
}  // namespace internal
template <class T, size_t N>
auto make_vector(const int (&sizes)[N], const T& init = T()) {
	vector s(rbegin(sizes), rend(sizes));
	return internal::make_vector<T, N>(s, init);
}
#line 7 "/home/yuruhiya/programming/library/template/template_no_Ruby.cpp"
#if __has_include(<library/dump.hpp>)
#include <library/dump.hpp>
#define LOCAL
#else
#define dump(...) ((void)0)
#endif

template <class T> constexpr T oj_local(const T& oj, const T& local) {
#ifndef LOCAL
	return oj;
#else
	return local;
#endif
}
#line 3 "/home/yuruhiya/programming/library/Utility/CulSum.cpp"
#include <type_traits>
#line 5 "/home/yuruhiya/programming/library/Utility/CulSum.cpp"
using namespace std;

template <class T> class CulSum {
public:
	using value_type = T;
	using data_type = vector<value_type>;

private:
	size_t n;
	data_type data;

public:
	CulSum() = default;
	CulSum(const data_type& a) : n(a.size()), data(n + 1) {
		for (size_t i = 0; i < n; ++i) {
			data[i + 1] = data[i] + a[i];
		}
	}
	template <class U, class F, enable_if_t<is_integral_v<U>, nullptr_t> = nullptr>
	CulSum(const U& _n, F f) : n(_n), data(n + 1) {
		for (size_t i = 0; i < n; ++i) {
			data[i + 1] = data[i] + static_cast<value_type>(f(i));
		}
	}
	template <class U, class F, enable_if_t<!is_integral_v<U>, nullptr_t> = nullptr>
	CulSum(const U& a, F f)
	    : CulSum(a.size(), [a, f](size_t i) -> value_type { return f(a[i]); }) {}
	size_t size() const {
		return n;
	}
	value_type at(size_t i) const {
		return operator()(i, i + 1);
	}
	// [l, r)
	value_type operator()(size_t l, size_t r) const {
		l = min(l, n);
		r = min(r, n);
		return l > r ? 0 : data[r] - data[l];
	}
	// [0, r)
	value_type operator()(size_t r) const {
		r = min(r, n);
		return data[r];
	}
	const data_type& get_data() const {
		return data;
	}
};
#line 5 "/home/yuruhiya/programming/library/Math/modint.cpp"
using namespace std;

template <int MOD> struct modint {
	using T = long long;
	T n;
	constexpr modint(const T x = 0) : n(x % MOD) {
		if (n < 0) n += MOD;
	}
	constexpr int get_mod() const {
		return MOD;
	}
	constexpr modint operator+() const {
		return *this;
	}
	constexpr modint operator-() const {
		return n ? MOD - n : 0;
	}
	constexpr modint& operator++() {
		if (MOD <= ++n) n = 0;
		return *this;
	}
	constexpr modint& operator--() {
		if (n <= 0) n = MOD;
		n--;
		return *this;
	}
	constexpr modint operator++(int) {
		modint t = *this;
		++*this;
		return t;
	}
	constexpr modint operator--(int) {
		modint t = *this;
		--*this;
		return t;
	}
	constexpr modint next() const {
		return ++modint(*this);
	}
	constexpr modint pred() const {
		return --modint(*this);
	}
	constexpr modint operator+(const modint& m) const {
		return modint(*this) += m;
	}
	constexpr modint operator-(const modint& m) const {
		return modint(*this) -= m;
	}
	constexpr modint operator*(const modint& m) const {
		return modint(*this) *= m;
	}
	constexpr modint operator/(const modint& m) const {
		return modint(*this) /= m;
	}
	constexpr modint& operator+=(const modint& m) {
		n += m.n;
		if (n >= MOD) n -= MOD;
		return *this;
	}
	constexpr modint& operator-=(const modint& m) {
		n -= m.n;
		if (n < 0) n += MOD;
		return *this;
	}
	constexpr modint& operator*=(const modint& m) {
		n = n * m.n % MOD;
		return *this;
	}
	constexpr modint& operator/=(const modint& m) {
		T a = m.n, b = MOD, u = 1, v = 0;
		while (b) {
			T t = a / b;
			a -= t * b;
			swap(a, b);
			u -= t * v;
			swap(u, v);
		}
		n = n * u % MOD;
		if (n < 0) n += MOD;
		return *this;
	}
	constexpr bool operator==(const modint& m) const {
		return n == m.n;
	}
	constexpr bool operator!=(const modint& m) const {
		return n != m.n;
	}
	template <class M> constexpr modint pow(M m) const {
		if (0 <= m) {
			modint t = n, result = 1;
			while (m > 0) {
				if (m & 1) {
					result *= t;
					m--;
				} else {
					t *= t;
					m >>= 1;
				}
			}
			return result;
		} else {
			return (modint(1) / n).pow(-m);
		}
	}
	template <class M> constexpr modint operator^(M m) const {
		return pow(m);
	}
	friend ostream& operator<<(ostream& os, const modint<MOD>& m) {
		return os << m.n;
	}
	friend istream& operator>>(istream& is, modint<MOD>& m) {
		long long x;
		cin >> x;
		m = modint(x);
		return is;
	}
};
using mint = modint<1000000007>;
using VM = vector<mint>;
mint operator""_m(unsigned long long n) {
	return n;
}
#line 5 "/home/yuruhiya/programming/library/Utility/Compress.cpp"
using namespace std;

template <class T> class Compress {
public:
	using value_type = T;

private:
	vector<value_type> v;
	bool flag = false;

public:
	Compress() {}
	template <class U> Compress(const U& a) {
		add(a);
	}
	Compress& add(const value_type& a) {
		flag = false;
		v.push_back(a);
		return *this;
	}
	template <class U> Compress& add(const vector<U>& a) {
		flag = false;
		for (const auto& i : a) add(i);
		return *this;
	}
	template <class U> Compress& add(const initializer_list<U>& a) {
		flag = false;
		for (const auto& v : a) add(v);
		return *this;
	}
	template <class U> Compress& operator<<(const U& a) {
		add(a);
		return *this;
	}
	void build() {
		sort(v.begin(), v.end());
		v.erase(unique(v.begin(), v.end()), v.end());
		flag = true;
	}
	int operator()(const value_type& x) const {
		assert(flag);
		return lower_bound(v.begin(), v.end(), x) - v.begin();
	}
	vector<int> operator()(const vector<value_type>& x) const {
		assert(flag);
		vector<int> result;
		result.reserve(x.size());
		for (const value_type& i : x) {
			result.push_back(lower_bound(v.begin(), v.end(), i) - v.begin());
		}
		return result;
	}
	int lower(const value_type& x) const {
		assert(flag);
		return lower_bound(v.begin(), v.end(), x) - v.begin();
	}
	int upper(const value_type& x) const {
		assert(flag);
		return upper_bound(v.begin(), v.end(), x) - v.begin();
	}
	int size() const {
		assert(flag);
		return v.size();
	}
	const vector<value_type>& operator*() const {
		assert(flag);
		return v;
	}
	const value_type& operator[](int i) const {
		assert(flag);
		return v[i];
	}
};
#line 5 "/home/yuruhiya/programming/library/DataStructure/SegmentTree.cpp"
using namespace std;

template <class T> class SegmentTree {
public:
	using value_type = T;
	using func_type = function<value_type(value_type, value_type)>;

private:
	int n, original_n;
	value_type init;
	vector<value_type> data;
	func_type func;
	static int ceil2(int n) {
		int m = 1;
		while (m < n) m *= 2;
		return m;
	}

	template <class C> int ff(int a, int b, const C& c, int k, int l, int r) const {
		if (!c(data[k]) || r <= a || b <= l) {
			return -1;
		} else if (k >= n) {
			return k - n;
		} else {
			int lv = ff(a, b, c, 2 * k, l, (l + r) / 2);
			if (lv != -1) return lv;
			return ff(a, b, c, 2 * k + 1, (l + r) / 2, r);
		}
	}
	template <class C> int fl(int a, int b, const C& c, int k, int l, int r) const {
		if (!c(data[k]) || r <= a || b <= l) {
			return -1;
		} else if (k >= n) {
			return k - n;
		} else {
			int rv = fl(a, b, c, 2 * k + 1, (l + r) / 2, r);
			if (rv != -1) return rv;
			return fl(a, b, c, 2 * k, l, (l + r) / 2);
		}
	}

public:
	SegmentTree(int _n, const value_type& init_, const func_type& _func)
	    : n(ceil2(_n)), original_n(_n), init(init_), data(n * 2, init), func(_func) {}
	SegmentTree(const vector<value_type>& vec, const value_type& init_,
	            const func_type& _func)
	    : init(init_), func(_func) {
		build(vec);
	}
	void build(const vector<value_type>& v) {
		n = ceil2(v.size());
		original_n = v.size();
		data.assign(n * 2, init);
		for (size_t i = 0; i < v.size(); ++i) {
			data[i + n] = v[i];
		}
		for (int i = n - 1; i > 0; --i) {
			data[i] = func(data[i * 2], data[i * 2 + 1]);
		}
	}
	void update(int i, const value_type& x) {
		assert(0 <= i && i < n);
		data[i += n] = x;
		while (i >>= 1) {
			data[i] = func(data[i * 2], data[i * 2 + 1]);
		}
	}
	void add(int i, const value_type& x) {
		update(i, operator[](i) + x);
	}
	value_type operator[](int i) const {
		assert(0 <= i && i < n);
		return data[i + n];
	}
	value_type operator()(int l, int r) const {
		assert(0 <= l && l < r && r <= n);
		value_type L = init, R = init;
		for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
			if (l & 1) L = func(L, data[l++]);
			if (r & 1) R = func(data[--r], R);
		}
		return func(L, R);
	}
	template <class C> int find_first(int l, int r, const C& c) const {
		return ff(l, r, c, 1, 0, n);
	}
	template <class C> int find_last(int l, int r, const C& c) const {
		return fl(l, r, c, 1, 0, n);
	}
	vector<value_type> to_a() const {
		vector<value_type> res(original_n);
		for (int i = 0; i < original_n; ++i) {
			res[i] = operator[](i);
		}
		return res;
	}
};
#line 6 "a.cpp"

int main() {
	ini(n);
	VVI a(n);
	rep(i, n) {
		a[i] = in[in.read<int>()];
		sort(all(a[i]));
	}

	Compress<int> cmp;
	cmp << a << 0;
	cmp.build();

	SegmentTree<mint> seg(cmp.size(), 0, [](mint a, mint b) { return a + b; });
	seg.add(cmp(0), 1);
	rep(i, n) {
		const auto& v = a[i];
		VM memo(v.size());
		rep(j, sz(v)) {
			memo[j] = seg(0, cmp.lower(v[j]));
		}
		rep(j, sz(v)) {
			seg.add(cmp(v[j]), memo[j]);
		}
	}
	out(seg(0, cmp.size()));
}
accuracy: 1
time_ms: 30
memory_kb: 8668
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;

const int MOD = 1e9 + 7;

const int N = 1e5 + 22;

int fenw[N];

int get(int r)
{
    int res = 0;
    while (r >= 0)
    {
        res = (res + fenw[r]) % MOD;
        r = (r & (r + 1)) - 1;
    }
    return res;
}

void add(int p, int x)
{
    while (p < N)
    {
        fenw[p] = (fenw[p] + x) % MOD;
        p |= (p + 1);
    }
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    int n;
    cin >> n;
    vector<vector<int> > a(n);
    vector<int> b;
    for (int i = 0; i < n; i++)
    {
        int m;
        cin >> m;
        a[i] = vector<int>(m);
        for (int j = 0; j < m; j++)
        {
            cin >> a[i][j];
            b.push_back(a[i][j]);
        }
        sort(a[i].rbegin(), a[i].rend());
    }
    b.push_back(0);
    sort(b.begin(), b.end());
    map<int, int> mm;
    for (int i = 0; i < b.size(); i++)
    {
        mm[b[i]] = i;
    }
    add(0, 1);
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < a[i].size(); j++)
        {
            a[i][j] = mm[a[i][j]];
            add(a[i][j], get(a[i][j] - 1));
        }
    }
    cout << get(N - 1) << endl;
}
accuracy: 1
time_ms: 60
memory_kb: 11216
final_rank: 6

code_snippet: #include <memory>
#include <cassert>
#include <cstdint>
#include <functional>

template<class Tp>
struct dynamic_segment_tree {
	using reference = Tp&;
	using const_reference = const Tp &;
	using size_type = std::uint_fast64_t;
	using binary_op = std::function<Tp(Tp, Tp)>;
	using value_type = Tp;
private :
	struct node_type;
	using node_ptr = std::unique_ptr<node_type>;

	size_type n;
	const Tp identity;
	const binary_op op;
	node_ptr root;

	struct node_type {
		value_type value;
		node_ptr left, right;
		node_type (const_reference value)
		noexcept : value(value), left(nullptr), right(nullptr) { }
	};

	const_reference get (const node_ptr &node) const noexcept {
		return (node ? node->value : identity);
	}

	void make_node (node_ptr &node) noexcept {
		node = std::make_unique<node_type>(identity);
	}

	value_type update (size_type i, const_reference x, node_ptr &node, size_type l, size_type r) noexcept {
		if (not node) make_node(node);
		if (r - l == 1) return node->value = x;
		const size_type mid = (l + r) >> 1;
		if (i < mid) return node->value = op(update(i, x, node->left, l, mid), get(node->right));
		else return node->value = op(get(node->left), update(i, x, node->right, mid, r));
	};

	value_type fold (size_type a, size_type b, node_ptr &node, size_type l, size_type r) const noexcept {
		if (a <= l and r <= b) return get(node);
		if (r <= a or  b <= l) return identity;
		const size_type mid = (l + r) >> 1;
		const value_type vl = (node->left ? fold(a, b, node->left, l, mid) : identity);
		const value_type vr = (node->right ? fold(a, b, node->right, mid, r) : identity);
		return op(vl, vr);
	}

public :
	dynamic_segment_tree (size_type n, const_reference identity, const binary_op &op)
	noexcept : n(n), identity(identity), op(op), root(std::make_unique<node_type>(identity)) { }

	void update (size_type index, const_reference x) noexcept {
		update(index, x, root, 0, n);
	}

	value_type fold (size_type first, size_type last) noexcept {
		return fold(first, last, root, 0, n);
	}

	value_type operator[] (const size_type &index) noexcept {
		return fold(index, index + 1);
	}

};



#include <iostream>
#include <cstdint>
#include <cassert>

template<std::int_fast32_t Modulus>
struct modint {
	using value_type = std::int_fast32_t;
	static constexpr value_type mod = Modulus;
	static_assert(mod > 1, "Modulus must be greater than 1");
private :
	value_type x;
	template<class T> static constexpr value_type normalize (T value) noexcept {
		if (value < 0) { value = (-value) % mod; return (value ? value : mod - value); }
		return (value % mod);
	}
public :
	explicit constexpr modint () noexcept : x(0) { }
	template<class T> constexpr modint (T value) noexcept : x(normalize(value)) { }
	constexpr modint operator+ () const noexcept { return modint(*this); }
	constexpr modint operator- () noexcept { if (x != 0) x = mod - x; return modint(*this); }
	constexpr modint &operator+= (const modint &p) noexcept { if ((x += p.x) >= mod) x -= mod; return (*this); }
	constexpr modint &operator-= (const modint &p) noexcept { if ((x += mod - p.x) >= mod) x -= mod; return (*this); }
	constexpr modint &operator*= (const modint &p) noexcept { x = (int)(1LL * x * p.x % mod); return (*this); }
	constexpr modint &operator/= (const modint &p) noexcept { return ((*this) *= p.inverse()); }
	constexpr modint operator+ (const modint &p) const noexcept { return (modint(*this) += p); }
	constexpr modint operator- (const modint &p) const noexcept { return (modint(*this) -= p); }
	constexpr modint operator* (const modint &p) const noexcept { return (modint(*this) *= p); }
	constexpr modint operator/ (const modint &p) const noexcept { return (modint(*this) /= p); }
	constexpr bool operator== (const modint &p) const noexcept { return (x == p.x); }
	constexpr bool operator!= (const modint &p) const noexcept { return (x != p.x); }
	constexpr modint inverse () const noexcept { return pow(mod - 2); }
	constexpr modint pow (std::uint_fast64_t exp) const noexcept {
		modint value(1), buff(x);
		while (exp) { if (exp & 1) value *= buff; buff *= buff; exp >>= 1; }
		return value;
	}
	friend std::ostream &operator<< (std::ostream &os, const modint &p) { return (os << p.x); }
	friend std::istream &operator>> (std::istream &is, modint &p) { long long v; is >> v; p = modint(v); return (is); }
};



#include <vector>
#include <algorithm>

constexpr std::int_fast32_t MOD = 1'000'000'007;

using mint = modint<MOD>;
using usize = typename dynamic_segment_tree<mint>::size_type;

constexpr usize MAX = 1'000'000'001;

int main() {
	size_t n;
	std::cin >> n;
	std::vector<usize> a;
	for (size_t i = 0; i < n; i++) {
		size_t m;
		std::cin >> m;
		std::vector<usize> b(m);
		for (auto &e : b) std::cin >> e;
		std::sort(b.begin(), b.end(), std::greater<usize>());
		a.insert(a.end(), b.begin(), b.end());
	}
	
	auto op = [](const modint<MOD> &a, const modint<MOD> &b) { return a + b; };
	dynamic_segment_tree<modint<MOD>> seg(MAX, 0, op);
	seg.update(0, 1);
	
	for (const auto &j : a) seg.update(j, seg.fold(0, j + 1));
	std::cout << seg.fold(0, MAX) << '\n';
	return 0;
}
accuracy: 1
time_ms: 130
memory_kb: 49016
final_rank: 13

code_snippet: #include <iostream>
#include <vector>
#include <functional>

template<class T> class dynamic_segment_tree {
	struct node {
		T value;
		node *communist = nullptr, *nationalist = nullptr;
		node(const T& id) : value(id) {}
	};
	node *root;
	const long long leftend, rightend;
	const std::function<T(T, T)> op;
	const T id;

	T merge(node *ptr) const {
		T ret = id;
		if (ptr -> communist) ret = op(ret, (ptr -> communist) -> value);
		if (ptr -> nationalist) ret = op(ret, (ptr -> nationalist) -> value);
		return ret;
	}

public :
	dynamic_segment_tree(const long long& l, const long long& r, const std::function<T(T, T)>& f, const T& t)
	: root(new node(t)), leftend(l), rightend(r), op(f), id(t) {}

	void point_update(const long long& k, const T& t, node *ptr = nullptr, long long l = -1, long long r = -1) const {
		if (!ptr) {
			ptr = root;
			l = leftend;
			r = rightend;
		}
		if (l + 1 == r) {
			(ptr -> value) = t;
			return;
		}
		long long mid = (l + r) / 2;
		if (k < mid) {
			if (!(ptr -> communist)) (ptr -> communist) = new node(id);
			point_update(k, t, ptr -> communist, l, mid);
		} else {
			if (!(ptr -> nationalist)) (ptr -> nationalist) = new node(id);
			point_update(k, t, ptr -> nationalist, mid, r);
		}
		(ptr -> value) = merge(ptr);
	}

	T range_fold(const long long& L, const long long& R, node *ptr = nullptr, long long l = -1, long long r = -1) const {
		if (!ptr) {
			ptr = root;
			l = leftend;
			r = rightend;
		}
		if (L <= l && r <= R) return (ptr -> value);
		T ret = id;
		long long mid = (l + r) / 2;
		if (L < mid && (ptr -> communist)) ret = op(ret, range_fold(L, R, ptr -> communist, l, mid));
		if (mid < R && (ptr -> nationalist)) ret = op(ret, range_fold(L, R, ptr -> nationalist, mid, r));
		return ret;
	}

	T operator[](const long long& k) const {return range_fold(k, k + 1);}
};

template<long long P> long long modinv(long long n) {
	long long a = P, u = 1, v = 0;
	while (a) {
		long long t = n / a;
		n -= t * a; std::swap(n, a);
		u -= t * v; std::swap(u, v);
	}
	if (u < 0 || P <= u) u %= P;
	return ((u < 0)?(u + P):u);
}

template<long long MOD> class modint {
	long long value;
public :
	modint(const long long& k = 0) : value(k) {
		if (value < 0 || MOD <= value) value %= MOD;
		if (value < 0) value += MOD;
	}
	const long long& get_value() const {return value;}
	modint<MOD> operator+(const modint<MOD>& rhs) const {
		long long ret = value + rhs.value;
		return {(ret >= MOD)?(ret - MOD):ret};
	}
	modint<MOD> operator-(const modint<MOD>& rhs) const {
		long long ret = value - rhs.value;
		return {(ret < 0)?(ret + MOD):ret};
	}
	modint<MOD> operator*(const modint<MOD>& rhs) const {
		long long ret = value * rhs.value;
		return {(ret >= MOD)?(ret % MOD):ret};
	}
	modint<MOD> operator/(const modint<MOD>& rhs) const {return *this * modinv<MOD>(rhs.value);}
	const modint<MOD>& operator+=(const modint<MOD>& rhs) {return *this = *this + rhs;}
	const modint<MOD>& operator-=(const modint<MOD>& rhs) {return *this = *this - rhs;}
	const modint<MOD>& operator*=(const modint<MOD>& rhs) {return *this = *this * rhs;}
	const modint<MOD>& operator/=(const modint<MOD>& rhs) {return *this = *this / rhs;}
	modint<MOD> operator-() const {return *this * (MOD - 1);}
	const modint<MOD>& operator++() {return *this += 1;}
	modint<MOD> operator++(int) {return ++(*this) - 1;}
	const modint<MOD>& operator--() {return *this -= 1;}
	modint<MOD> operator--(int) {return --(*this) + 1;}
	bool operator==(const modint<MOD>& rhs) const {return (value == rhs.value);}
	bool operator!=(const modint<MOD>& rhs) const {return (value != rhs.value);}
};
template<long long MOD> modint<MOD> operator+(const long long& lhs, const modint<MOD>& rhs) {return rhs + lhs;}
template<long long MOD> modint<MOD> operator-(const long long& lhs, const modint<MOD>& rhs) {return (-rhs) + lhs;}
template<long long MOD> modint<MOD> operator*(const long long& lhs, const modint<MOD>& rhs) {return rhs * lhs;}
template<long long MOD> bool operator==(const long long& lhs, const modint<MOD>& rhs) {return (lhs == rhs.get_value());}
template<long long MOD> bool operator!=(const long long& lhs, const modint<MOD>& rhs) {return (lhs != rhs.get_value());}

std::vector<long long> factorial, factorial_inv;

template<long long P> void make_table(const int& n) {
	factorial.resize(n + 1, 1);
	factorial_inv.resize(n + 1, 1);
	modint<P> x = 1;
	for (int i = 2; i <= n; i++) factorial[i] = (x *= i).get_value();
	x = factorial_inv[n] = modinv<P>(factorial[n]);
	for (int i = n - 1; i > 1; i--) factorial_inv[i] = (x *= (i + 1)).get_value();
}

template<long long P> modint<P> permutation(const int& n, int r) {
	if (n >= (int)factorial.size()) {
		std::cerr << "permutation(" << n << ", " << r << ") called.\n";
		std::cerr << "warning : factorial table not constructed, or its size is smaller than 'n'.\n";
		modint<P> ret = 1;
		for (int i = 0; i < r; i++) ret *= n - i;
		return ret;
	} else return {factorial[n] * factorial_inv[n - r]};
}

template<long long P> modint<P> combination(const int& n, int r) {
	modint<P> ret = 1;
	if (n >= (int)factorial.size()) {
		std::cerr << "combination(" << n << ", " << r << ") called.\n";
		std::cerr << "warning : factorial table not constructed, or its size is smaller than 'n'.\n";
		r = std::min(r, n - r);
		for (int i = 0; i < r; i++) {
			ret *= n - i;
			ret /= i + 1;
		}
	} else {
		ret *= factorial[n];
		ret *= factorial_inv[n - r];
		ret *= factorial_inv[r];
	}
	return ret;
}

long long modpow(long long a, const long long& n, const long long& MOD) {
	if (n == 0) return 1;
	if (a < 0 || MOD <= a) a %= MOD;
	if (a < 0) a += MOD;
	long long ret = a, cnt = 1;
	while (cnt * 2 <= n) {
		ret *= ret;
		if (ret >= MOD) ret %= MOD;
		cnt *= 2;
	}
	ret *= modpow(a, n - cnt, MOD);
	if (ret >= MOD) ret %= MOD;
	return ret;
}

template<long long MOD> modint<MOD> modpow(const modint<MOD>& a, const long long& n) {
	if (n == 0) return 1;
	modint<MOD> ret = a;
	long long cnt = 1;
	while (cnt * 2 <= n) {
		ret *= ret;
		cnt *= 2;
	}
	return ret * modpow<MOD>(a, n - cnt);
}

template<long long MOD> std::istream& operator>>(std::istream& lhs, modint<MOD>& rhs) {
	long long value;
	lhs >> value;
	rhs = modint<MOD>(value);
	return lhs;
}

template<long long MOD> std::ostream& operator<<(std::ostream& lhs, const modint<MOD>& rhs) {
	return lhs << rhs.get_value();
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);

	int N;
	std::cin >> N;
	std::vector<std::vector<int>> A(N);
	for (int i = 0; i < N; i++) {
		int M;
		std::cin >> M;
		A[i].resize(M);
		for (int j = 0; j < M; j++) std::cin >> A[i][j];
		sort(A[i].rbegin(), A[i].rend());
	}

	constexpr int P = 1000000007;
	dynamic_segment_tree<modint<P>> sg(0, 1000000001, [](modint<P> a, modint<P> b){return a + b;}, 0);
	sg.point_update(0, 1);

	for (int i = 0; i < N; i++) {
		for (const int& j : A[i]) {
			sg.point_update(j, sg[j] + sg.range_fold(0, j));
		}
	}

	std::cout << sg.range_fold(0, 1000000001) << '\n';
}
accuracy: 1
time_ms: 100
memory_kb: 51004
final_rank: 10

code_snippet: #include <iostream>
#include <vector>
#include <functional>

template<class T> class dynamic_segment_tree {
	struct node {
		T value;
		node *communist = nullptr, *nationalist = nullptr;
		node(const T& id) : value(id) {}
	};
	node *root;
	const long long leftend, rightend;
	const std::function<T(T, T)> op;
	const T id;

	T merge(node *ptr) const {
		T ret = id;
		if (ptr -> communist) ret = op(ret, (ptr -> communist) -> value);
		if (ptr -> nationalist) ret = op(ret, (ptr -> nationalist) -> value);
		return ret;
	}

public :
	dynamic_segment_tree(const long long& l, const long long& r, const std::function<T(T, T)>& f, const T& t)
	: root(new node(t)), leftend(l), rightend(r), op(f), id(t) {}

	void point_update(const long long& k, const T& t, node *ptr = nullptr, long long l = -1, long long r = -1) const {
		if (!ptr) {
			ptr = root;
			l = leftend;
			r = rightend;
		}
		if (l + 1 == r) {
			(ptr -> value) = t;
			return;
		}
		long long mid = (l + r) / 2;
		if (k < mid) {
			if (!(ptr -> communist)) (ptr -> communist) = new node(id);
			point_update(k, t, ptr -> communist, l, mid);
		} else {
			if (!(ptr -> nationalist)) (ptr -> nationalist) = new node(id);
			point_update(k, t, ptr -> nationalist, mid, r);
		}
		(ptr -> value) = merge(ptr);
	}

	T range_fold(const long long& L, const long long& R, node *ptr = nullptr, long long l = -1, long long r = -1) const {
		if (!ptr) {
			ptr = root;
			l = leftend;
			r = rightend;
		}
		if (L <= l && r <= R) return (ptr -> value);
		T ret = id;
		long long mid = (l + r) / 2;
		if (L < mid && (ptr -> communist)) ret = op(ret, range_fold(L, R, ptr -> communist, l, mid));
		if (mid < R && (ptr -> nationalist)) ret = op(ret, range_fold(L, R, ptr -> nationalist, mid, r));
		return ret;
	}

	T operator[](const long long& k) const {return range_fold(k, k + 1);}
};

template<long long P> long long modinv(long long n) {
	long long a = P, u = 1, v = 0;
	while (a) {
		long long t = n / a;
		n -= t * a; std::swap(n, a);
		u -= t * v; std::swap(u, v);
	}
	if (u < 0 || P <= u) u %= P;
	return ((u < 0)?(u + P):u);
}

template<long long MOD> class modint {
	long long value;
public :
	modint(const long long& k = 0) : value(k) {
		if (value < 0 || MOD <= value) value %= MOD;
		if (value < 0) value += MOD;
	}
	const long long& get_value() const {return value;}
	modint<MOD> operator+(const modint<MOD>& rhs) const {
		long long ret = value + rhs.value;
		return {(ret >= MOD)?(ret - MOD):ret};
	}
	modint<MOD> operator-(const modint<MOD>& rhs) const {
		long long ret = value - rhs.value;
		return {(ret < 0)?(ret + MOD):ret};
	}
	modint<MOD> operator*(const modint<MOD>& rhs) const {
		long long ret = value * rhs.value;
		return {(ret >= MOD)?(ret % MOD):ret};
	}
	modint<MOD> operator/(const modint<MOD>& rhs) const {return *this * modinv<MOD>(rhs.value);}
	const modint<MOD>& operator+=(const modint<MOD>& rhs) {return *this = *this + rhs;}
	const modint<MOD>& operator-=(const modint<MOD>& rhs) {return *this = *this - rhs;}
	const modint<MOD>& operator*=(const modint<MOD>& rhs) {return *this = *this * rhs;}
	const modint<MOD>& operator/=(const modint<MOD>& rhs) {return *this = *this / rhs;}
	modint<MOD> operator-() const {return *this * (MOD - 1);}
	const modint<MOD>& operator++() {return *this += 1;}
	modint<MOD> operator++(int) {return ++(*this) - 1;}
	const modint<MOD>& operator--() {return *this -= 1;}
	modint<MOD> operator--(int) {return --(*this) + 1;}
	bool operator==(const modint<MOD>& rhs) const {return (value == rhs.value);}
	bool operator!=(const modint<MOD>& rhs) const {return (value != rhs.value);}
};
template<long long MOD> modint<MOD> operator+(const long long& lhs, const modint<MOD>& rhs) {return rhs + lhs;}
template<long long MOD> modint<MOD> operator-(const long long& lhs, const modint<MOD>& rhs) {return (-rhs) + lhs;}
template<long long MOD> modint<MOD> operator*(const long long& lhs, const modint<MOD>& rhs) {return rhs * lhs;}
template<long long MOD> bool operator==(const long long& lhs, const modint<MOD>& rhs) {return (lhs == rhs.get_value());}
template<long long MOD> bool operator!=(const long long& lhs, const modint<MOD>& rhs) {return (lhs != rhs.get_value());}

std::vector<long long> factorial, factorial_inv;

template<long long P> void make_table(const int& n) {
	factorial.resize(n + 1, 1);
	factorial_inv.resize(n + 1, 1);
	modint<P> x = 1;
	for (int i = 2; i <= n; i++) factorial[i] = (x *= i).get_value();
	x = factorial_inv[n] = modinv<P>(factorial[n]);
	for (int i = n - 1; i > 1; i--) factorial_inv[i] = (x *= (i + 1)).get_value();
}

template<long long P> modint<P> permutation(const int& n, int r) {
	if (n >= (int)factorial.size()) {
		std::cerr << "permutation(" << n << ", " << r << ") called.\n";
		std::cerr << "warning : factorial table not constructed, or its size is smaller than 'n'.\n";
		modint<P> ret = 1;
		for (int i = 0; i < r; i++) ret *= n - i;
		return ret;
	} else return {factorial[n] * factorial_inv[n - r]};
}

template<long long P> modint<P> combination(const int& n, int r) {
	modint<P> ret = 1;
	if (n >= (int)factorial.size()) {
		std::cerr << "combination(" << n << ", " << r << ") called.\n";
		std::cerr << "warning : factorial table not constructed, or its size is smaller than 'n'.\n";
		r = std::min(r, n - r);
		for (int i = 0; i < r; i++) {
			ret *= n - i;
			ret /= i + 1;
		}
	} else {
		ret *= factorial[n];
		ret *= factorial_inv[n - r];
		ret *= factorial_inv[r];
	}
	return ret;
}

long long modpow(long long a, const long long& n, const long long& MOD) {
	if (n == 0) return 1;
	if (a < 0 || MOD <= a) a %= MOD;
	if (a < 0) a += MOD;
	long long ret = a, cnt = 1;
	while (cnt * 2 <= n) {
		ret *= ret;
		if (ret >= MOD) ret %= MOD;
		cnt *= 2;
	}
	ret *= modpow(a, n - cnt, MOD);
	if (ret >= MOD) ret %= MOD;
	return ret;
}

template<long long MOD> modint<MOD> modpow(const modint<MOD>& a, const long long& n) {
	if (n == 0) return 1;
	modint<MOD> ret = a;
	long long cnt = 1;
	while (cnt * 2 <= n) {
		ret *= ret;
		cnt *= 2;
	}
	return ret * modpow<MOD>(a, n - cnt);
}

template<long long MOD> std::istream& operator>>(std::istream& lhs, modint<MOD>& rhs) {
	long long value;
	lhs >> value;
	rhs = modint<MOD>(value);
	return lhs;
}

template<long long MOD> std::ostream& operator<<(std::ostream& lhs, const modint<MOD>& rhs) {
	return lhs << rhs.get_value();
}

int main() {
	int N;
	std::cin >> N;
	std::vector<std::vector<int>> A(N);
	for (int i = 0; i < N; i++) {
		int M;
		std::cin >> M;
		A[i].resize(M);
		for (int j = 0; j < M; j++) std::cin >> A[i][j];
		sort(A[i].rbegin(), A[i].rend());
	}

	constexpr int P = 1000000007;
	dynamic_segment_tree<modint<P>> sg(0, 1000000001, [](modint<P> a, modint<P> b){return a + b;}, 0);
	sg.point_update(0, 1);

	for (int i = 0; i < N; i++) {
		for (const int& j : A[i]) {
			sg.point_update(j, sg[j] + sg.range_fold(0, j));
		}
	}

	std::cout << sg.range_fold(0, 1000000001) << '\n';
}
accuracy: 1
time_ms: 120
memory_kb: 50864
final_rank: 11

code_snippet: #include <iostream>
#include <functional>

template<class T> class dynamic_segment_tree {
public :
	struct node {
		T value;
		node *communist = nullptr, *nationalist = nullptr;
		node(const T& id) : value(id) {}
	};
	node *root;
	const long long leftend, rightend;
	const std::function<T(T, T)> op;
	const T id;

	dynamic_segment_tree(const long long& l, const long long& r, const std::function<T(T, T)>& f, const T& t)
	: root(new node(t)), leftend(l), rightend(r), op(f), id(t) {}

	T merge(node *ptr) const {
		T ret = id;
		if (ptr -> communist) ret = op(ret, (ptr -> communist) -> value);
		if (ptr -> nationalist) ret = op(ret, (ptr -> nationalist) -> value);
		return ret;
	}

	void point_update(const long long& k, const T& t, node *ptr = nullptr, long long l = -1, long long r = -1) const {
		if (!ptr) {
			ptr = root;
			l = leftend;
			r = rightend;
		}
		if (l + 1 == r) {
			(ptr -> value) = t;
			return;
		}
		long long mid = (l + r) / 2;
		if (k < mid) {
			if (!(ptr -> communist)) (ptr -> communist) = new node(id);
			point_update(k, t, ptr -> communist, l, mid);
		} else {
			if (!(ptr -> nationalist)) (ptr -> nationalist) = new node(id);
			point_update(k, t, ptr -> nationalist, mid, r);
		}
		(ptr -> value) = merge(ptr);
	}

	T range_fold(const long long& L, const long long& R, node *ptr = nullptr, long long l = -1, long long r = -1) const {
		if (!ptr) {
			ptr = root;
			l = leftend;
			r = rightend;
		}
		if (L <= l && r <= R) return (ptr -> value);
		T ret = id;
		long long mid = (l + r) / 2;
		if (L < mid && (ptr -> communist)) ret = op(ret, range_fold(L, R, ptr -> communist, l, mid));
		if (mid < R && (ptr -> nationalist)) ret = op(ret, range_fold(L, R, ptr -> nationalist, mid, r));
		return ret;
	}

	T operator[](const long long& k) {return range_fold(k, k + 1);}
};

/*	last verified	: 2020/10/07
	problem			: https://atcoder.jp/contests/atc002/tasks/atc002_b
	submission		: https://atcoder.jp/contests/atc002/submissions/17232093
	problem			: https://atcoder.jp/contests/practice2/tasks/practice2_k
	submission		: https://atcoder.jp/contests/practice2/submissions/17232101
	problem			: https://atcoder.jp/contests/abc160/tasks/abc160_f
	submission		: https://atcoder.jp/contests/abc160/submissions/17232113
	problem			: https://atcoder.jp/contests/abc152/tasks/abc152_e
	submission		: https://atcoder.jp/contests/abc152/submissions/17260558
*/
#include <iostream>
#include <vector>

template<long long P> long long modinv(long long n) {
	long long a = P, u = 1, v = 0;
	while (a) {
		long long t = n / a;
		n -= t * a; std::swap(n, a);
		u -= t * v; std::swap(u, v);
	}
	if (u < 0 || P <= u) u %= P;
	return ((u < 0)?(u + P):u);
}

template<long long MOD> class modint {
	long long value;
public :
	modint(const long long& k = 0) : value(k) {
		if (value < 0 || MOD <= value) value %= MOD;
		if (value < 0) value += MOD;
	}
	const long long& get_value() const {return value;}
	modint<MOD> operator+(const modint<MOD>& rhs) const {
		long long ret = value + rhs.value;
		return {(ret >= MOD)?(ret - MOD):ret};
	}
	modint<MOD> operator-(const modint<MOD>& rhs) const {
		long long ret = value - rhs.value;
		return {(ret < 0)?(ret + MOD):ret};
	}
	modint<MOD> operator*(const modint<MOD>& rhs) const {
		long long ret = value * rhs.value;
		return {(ret >= MOD)?(ret % MOD):ret};
	}
	modint<MOD> operator/(const modint<MOD>& rhs) const {return *this * modinv<MOD>(rhs.value);}
	const modint<MOD>& operator+=(const modint<MOD>& rhs) {return *this = *this + rhs;}
	const modint<MOD>& operator-=(const modint<MOD>& rhs) {return *this = *this - rhs;}
	const modint<MOD>& operator*=(const modint<MOD>& rhs) {return *this = *this * rhs;}
	const modint<MOD>& operator/=(const modint<MOD>& rhs) {return *this = *this / rhs;}
	modint<MOD> operator-() const {return *this * (MOD - 1);}
	const modint<MOD>& operator++() {return *this += 1;}
	modint<MOD> operator++(int) {return ++(*this) - 1;}
	const modint<MOD>& operator--() {return *this -= 1;}
	modint<MOD> operator--(int) {return --(*this) + 1;}
	bool operator==(const modint<MOD>& rhs) const {return (value == rhs.value);}
	bool operator!=(const modint<MOD>& rhs) const {return (value != rhs.value);}
};
template<long long MOD> modint<MOD> operator+(const long long& lhs, const modint<MOD>& rhs) {return rhs + lhs;}
template<long long MOD> modint<MOD> operator-(const long long& lhs, const modint<MOD>& rhs) {return (-rhs) + lhs;}
template<long long MOD> modint<MOD> operator*(const long long& lhs, const modint<MOD>& rhs) {return rhs * lhs;}
template<long long MOD> bool operator==(const long long& lhs, const modint<MOD>& rhs) {return (lhs == rhs.get_value());}
template<long long MOD> bool operator!=(const long long& lhs, const modint<MOD>& rhs) {return (lhs != rhs.get_value());}

std::vector<long long> factorial, factorial_inv;

template<long long P> void make_table(const int& n) {
	factorial.resize(n + 1, 1);
	factorial_inv.resize(n + 1, 1);
	modint<P> x = 1;
	for (int i = 2; i <= n; i++) factorial[i] = (x *= i).get_value();
	x = factorial_inv[n] = modinv<P>(factorial[n]);
	for (int i = n - 1; i > 1; i--) factorial_inv[i] = (x *= (i + 1)).get_value();
}

template<long long P> modint<P> permutation(const int& n, int r) {
	if (n >= (int)factorial.size()) {
		std::cerr << "permutation(" << n << ", " << r << ") called.\n";
		std::cerr << "warning : factorial table not constructed, or its size is smaller than 'n'.\n";
		modint<P> ret = 1;
		for (int i = 0; i < r; i++) ret *= n - i;
		return ret;
	} else return {factorial[n] * factorial_inv[n - r]};
}

template<long long P> modint<P> combination(const int& n, int r) {
	modint<P> ret = 1;
	if (n >= (int)factorial.size()) {
		std::cerr << "combination(" << n << ", " << r << ") called.\n";
		std::cerr << "warning : factorial table not constructed, or its size is smaller than 'n'.\n";
		r = std::min(r, n - r);
		for (int i = 0; i < r; i++) {
			ret *= n - i;
			ret /= i + 1;
		}
	} else {
		ret *= factorial[n];
		ret *= factorial_inv[n - r];
		ret *= factorial_inv[r];
	}
	return ret;
}

long long modpow(long long a, const long long& n, const long long& MOD) {
	if (n == 0) return 1;
	if (a < 0 || MOD <= a) a %= MOD;
	if (a < 0) a += MOD;
	long long ret = a, cnt = 1;
	while (cnt * 2 <= n) {
		ret *= ret;
		if (ret >= MOD) ret %= MOD;
		cnt *= 2;
	}
	ret *= modpow(a, n - cnt, MOD);
	if (ret >= MOD) ret %= MOD;
	return ret;
}

template<long long MOD> modint<MOD> modpow(const modint<MOD>& a, const long long& n) {
	if (n == 0) return 1;
	modint<MOD> ret = a;
	long long cnt = 1;
	while (cnt * 2 <= n) {
		ret *= ret;
		cnt *= 2;
	}
	return ret * modpow<MOD>(a, n - cnt);
}

template<long long MOD> std::istream& operator>>(std::istream& lhs, modint<MOD>& rhs) {
	long long value;
	lhs >> value;
	rhs = modint<MOD>(value);
	return lhs;
}

template<long long MOD> std::ostream& operator<<(std::ostream& lhs, const modint<MOD>& rhs) {
	return lhs << rhs.get_value();
}

int main() {
	int N;
	std::cin >> N;
	std::vector<std::vector<int>> A(N);
	for (int i = 0; i < N; i++) {
		int M;
		std::cin >> M;
		A[i].resize(M);
		for (int j = 0; j < M; j++) std::cin >> A[i][j];
		sort(A[i].rbegin(), A[i].rend());
	}

	constexpr int P = 1000000007;
	dynamic_segment_tree<modint<P>> sg(0, P, [](modint<P> a, modint<P> b){return a + b;}, 0);
	sg.point_update(0, 1);

	for (int i = 0; i < N; i++) {
		for (const int& j : A[i]) {
			sg.point_update(j, sg[j] + sg.range_fold(0, j));
		}
	}

	std::cout << sg.range_fold(0, P) << '\n';
}
accuracy: 1
time_ms: 120
memory_kb: 50940
final_rank: 12

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define SIZE 100005

int num_group,N;
ll BIT[SIZE],work[SIZE];
vector<ll> A[SIZE];
vector<int> V;
map<ll,int> MAP;


void add(int loc,ll value){

	BIT[loc] += value;

	loc += loc & -loc;

	while(loc <= N){
		BIT[loc] += value;
		BIT[loc] %= MOD;
		loc += loc & -loc;
	}
}

ll getSum(int loc){

	if(loc == 0)return 0;

	ll sum = BIT[loc];

	loc -= loc & -loc;

	while(loc > 0){
		sum += BIT[loc];
		sum %= MOD;
		loc -= loc & -loc;
	}
	return sum;
}

ll calc(int left,int right){
	return (getSum(right)-getSum(left-1)+MOD)%MOD;
}

int main(){

	scanf("%d",&num_group);

	int tmp_num;
	ll tmp;

	for(int i = 0; i < num_group; i++){

		scanf("%d",&tmp_num);
		for(int k = 0; k < tmp_num; k++){
			scanf("%lld",&tmp);
			A[i].push_back(tmp);
			V.push_back(tmp);
		}
	}

	sort(V.begin(),V.end());
	V.erase(unique(V.begin(),V.end()),V.end());

	N = 0;
	for(int i = 0; i < V.size(); i++){

		MAP[V[i]] = ++N;
	}

	for(int i = 0; i <= N; i++)BIT[i] = 0;

	ll ans = 1;


	for(int i = 0; i < num_group; i++){
		for(int k = 0; k < A[i].size(); k++){
			tmp = getSum(MAP[A[i][k]]-1)+1;
			ans += tmp;
			ans %= MOD;
			work[k] = tmp;
		}
		for(int k = 0; k < A[i].size(); k++){
			add(MAP[A[i][k]],work[k]);
		}
	}

	printf("%lld\n",ans);

	return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 14420
final_rank: 8

code_snippet: #include "iostream"
#include "climits"
#include "list"
#include "queue"
#include "stack"
#include "set"
#include "functional"
#include "algorithm"
#include "string"
#include "map"
#include "unordered_map"
#include "unordered_set"
#include "iomanip"
#include "cmath"
#include "random"
#include "bitset"
#include "cstdio"
#include "numeric"
#include "cassert"
#include "ctime"


using namespace std;

constexpr long long int MOD = 1000000007;
//constexpr int MOD = 1000000007;
//constexpr int MOD = 998244353;
//constexpr long long int MOD = 998244353;
constexpr double EPS = 1e-12;

//int N, M, K, T, H, W, L, R;
long long int N, M, K, T, H, W, L, R;

class Add_Segment_Tree {
	vector<long long int>v;
	long long int ret;
	int num;
	long long int Update(int place) {
		if (place >= v.size() / 2) {
			return v[place];
		}
		v[place] = Update(place * 2) + Update(place * 2 + 1);
		return v[place];
	}
public:
	Add_Segment_Tree(int n) {
		n++;
		num = 1;
		while (num < n * 2)num *= 2;
		v.resize(num, 0);
	}
	void Add(int place, long long int num, bool update) {
		place += v.size() / 2;
		v[place] += num;
		if (!update)return;
		place /= 2;
		while (place) {
			v[place] = v[place * 2] + v[place * 2 + 1];
			place /= 2;
		}
	}
	void TopDown() {
		Update(1);
	}
	long long int Sum(int a, int b) {
		ret = 0;
		b++;
		for (a += num / 2, b += num / 2; a < b; a >>= 1, b >>= 1) {
			if (a & 1)ret += v[a++];
			if (b & 1)ret += v[--b];
		}
		return ret;
	}
};

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);

	map<pair<int, int>,int>mp;
	cin >> N;
	mp[{-1, -1}] = 0;
	vector<vector<int>>v(N);
	int cnt = 0;
	for (auto &i : v) {
		cin >> M;
		i.resize(M);
		for (auto &j : i) {
			cin >> j;
			mp[{j, -cnt}] = 0;
		}
		sort(i.rbegin(), i.rend());
		cnt++;
	}
	cnt = 0;
	for (auto &i : mp) {
		i.second = cnt++;
	}
	Add_Segment_Tree asg(cnt);
	asg.Add(0, 1, true);
	for (int i = 0; i < N; i++) {
		for (auto j : v[i]) {
			long long int box = asg.Sum(0, mp[{j, -i}] - 1);
			box %= MOD;
			asg.Add(mp[{j, -i}], box, true);
		}
	}
	cout << asg.Sum(0, cnt) % MOD << endl;
}
accuracy: 1
time_ms: 70
memory_kb: 14084
final_rank: 7

code_snippet: /**
 *   @FileName	a.cpp
 *   @Author	kanpurin
 *   @Created	2020.09.22 22:35:27
**/

#include "bits/stdc++.h" 
using namespace std; 
typedef long long ll;



template< typename T >
struct BinaryIndexedTree {
    std::vector< T > data;
    BinaryIndexedTree(int sz) {
        data.assign(++sz, 0);
    }
    
    inline T sum(int k) {
        T ret = 0;
        for (++k; k > 0; k -= k & -k) ret += data[k];
        return (ret);
    }
    
    inline T sum(int left, int right) {
        return sum(right) - sum(left - 1);
    }
    
    
    inline void add(int k, T x) {
        for (++k; k < data.size(); k += k & -k) data[k] += x;
    }
    
    int lower_bound(ll k) {
        if (k <= 0) return 0;
        int res = 0;
        int N = 1; while (N < (int)data.size()) N *= 2;
        for (int i = N / 2; i > 0; i /= 2) {
            if (res + i < (int)data.size() && data[res + i] < k) {
                k -= data[res + i];
                res += i;
            }
        }
        return res;
    }
    void print() {
        std::cout << "[ ";
        for (int i = 0; i < data.size() - 1; i++) {
            std::cout << sum(i, i);
            if (i < data.size() - 2) cout << ", ";
        }
        std::cout << " ]" << endl;
    }
};
template< int MOD >
struct mint {
public:
    long long x;
    mint(long long x = 0) :x((x%MOD+MOD)%MOD) {}
    mint(std::string &s) {
        long long z = 0;
        for (int i = 0; i < s.size(); i++) {
            z *= 10;
            z += s[i] - '0';
            z %= MOD;
        }
        this->x = z;
    }
    mint& operator+=(const mint &a) {
        if ((x += a.x) >= MOD) x -= MOD;
        return *this;
    }
    mint& operator-=(const mint &a) {
        if ((x += MOD - a.x) >= MOD) x -= MOD;
        return *this;
    }
    mint& operator*=(const mint &a) {
        (x *= a.x) %= MOD;
        return *this;
    }
    mint& operator/=(const mint &a) {
        long long n = MOD - 2;
        mint u = 1, b = a;
        while (n > 0) {
            if (n & 1) {
                u *= b;
            }
            b *= b;
            n >>= 1;
        }
        return *this *= u;
    }
    mint operator+(const mint &a) const {
        mint res(*this);
        return res += a;
    }
    mint operator-() const {return mint() -= *this; }
    mint operator-(const mint &a) const {
        mint res(*this);
        return res -= a;
    }
    mint operator*(const mint &a) const {
        mint res(*this);
        return res *= a;
    }
    mint operator/(const mint &a) const {
        mint res(*this);
        return res /= a;
    }
    friend std::ostream& operator<<(std::ostream &os, const mint &n) {
        return os << n.x;
    }
    friend std::istream &operator>>(std::istream &is, mint &n) {
        long long x;
        is >> x;
        n = mint(x);
        return is;
    }
    bool operator==(const mint &a) const {
        return this->x == a.x;
    }
    mint pow(long long k) const {
        mint ret = 1;
        mint p = this->x;
        while (k > 0) {
            if (k & 1) {
                ret *= p;
            }
            p *= p;
            k >>= 1;
        }
        return ret;
    }
};
constexpr int MOD = 1e9 + 7;
int main() {
    int n;cin >> n;
    map<int,int> mp;
    vector<vector<int>> a(n);
    for (int i = 0; i < n; i++) {
        int m;cin >> m;
        for (int j = 0; j < m; j++) {
            int b;cin >> b;
            mp[b] = 0;
            a[i].push_back(b);
        }
    }
    int t = 1;
    for(auto p : mp) {
        mp[p.first] = t++;
    }
    BinaryIndexedTree<mint<MOD>> bit(t);
    mint<MOD> ans = 1;
    bit.add(0,1);
    for (int i = 0; i < n; i++) {
        vector<pair<mint<MOD>,int>> tmp;
        for (int j = 0; j < a[i].size(); j++) {
            mint<MOD> sum = bit.sum(mp[a[i][j]]-1);
            ans += sum;
            tmp.push_back({sum,mp[a[i][j]]});
        }
        for (int j = 0; j < tmp.size(); j++) {
            bit.add(tmp[j].second,tmp[j].first);
        }
    }
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 11240
final_rank: 9

code_snippet: /**
 *   @FileName	a.cpp
 *   @Author	kanpurin
 *   @Created	2020.09.22 22:33:35
**/

#include "bits/stdc++.h" 
using namespace std; 
typedef long long ll;



template< typename T >
struct BinaryIndexedTree {
    std::vector< T > data;
    BinaryIndexedTree(int sz) {
        data.assign(++sz, 0);
    }
    
    inline T sum(int k) {
        T ret = 0;
        for (++k; k > 0; k -= k & -k) ret += data[k];
        return (ret);
    }
    
    inline T sum(int left, int right) {
        return sum(right) - sum(left - 1);
    }
    
    
    inline void add(int k, T x) {
        for (++k; k < data.size(); k += k & -k) data[k] += x;
    }
    
    int lower_bound(ll k) {
        if (k <= 0) return 0;
        int res = 0;
        int N = 1; while (N < (int)data.size()) N *= 2;
        for (int i = N / 2; i > 0; i /= 2) {
            if (res + i < (int)data.size() && data[res + i] < k) {
                k -= data[res + i];
                res += i;
            }
        }
        return res;
    }
    void print() {
        std::cout << "[ ";
        for (int i = 0; i < data.size() - 1; i++) {
            std::cout << sum(i, i);
            if (i < data.size() - 2) cout << ", ";
        }
        std::cout << " ]" << endl;
    }
};
int main() {
    int n;cin >> n;
    map<int,int> mp;
    vector<vector<int>> a(n);
    for (int i = 0; i < n; i++) {
        int m;cin >> m;
        for (int j = 0; j < m; j++) {
            int b;cin >> b;
            mp[b] = 0;
            a[i].push_back(b);
        }
    }
    int t = 1;
    for(auto p : mp) {
        mp[p.first] = t++;
    }
    BinaryIndexedTree<int> bit(t);
    ll ans = 1;
    bit.add(0,1);
    for (int i = 0; i < n; i++) {
        vector<pair<int,int>> tmp;
        for (int j = 0; j < a[i].size(); j++) {
            int sum = bit.sum(mp[a[i][j]]-1);
            ans += sum;
            tmp.push_back({sum,mp[a[i][j]]});
        }
        for (int j = 0; j < tmp.size(); j++) {
            bit.add(tmp[j].second,tmp[j].first);
        }
    }
    cout << ans << endl;
    return 0;
}
accuracy: 0.3181818181818182
time_ms: 90
memory_kb: 10412
final_rank: 15

code_snippet: #pragma GCC optimize ("O3")
#include <iostream>
#include <iomanip>
#include <istream>
#include <ostream>
#include <sstream>
#include <iterator>
#include <vector>
#include <algorithm>
#include <queue>
#include <deque>
#include <list>
#include <stack>
#include <map>
#include <unordered_map>
#include <set>
#include <bitset>
#include <utility>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <string>
#include <ctime>
#include <cctype>
#include <cstdlib>
#include <numeric>
#define IINF 1000000000
//#define INF 3223372036854775807
#define MOD 1000000007
#define mod 1000000007
#define INT_MAX_ 2147483647
#define EPS (1e-10)
#define REP(i, a, n) fo-r (ll i = a; i < (ll)(n); i++)
#define REPE(i, a, n) for (ll i = a; i <= (ll)(n); i++)
//#define rep(i,n)for (ll i = 0; i < (ll)(n); i++)
#define rep(i,l,r)for(ll i=(l);i<(r);i++)
#define rep1(i,n) for(int i=1;i<=(int)(n);i++)
#define Endl endl
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define eb emplace_back
#define mmax(x,y)(x>y?x:y)
#define mmin(x,y)(x<y?x:y)
#define chmax(x,y) x=mmax(x,y)
#define chmin(x,y) x=mmin(x,y)
#define all(x) (x).begin(),(x).end()
#define siz(x) (ll)(x).size()
#define PI acos(-1.0)
#define me memset
#define bit(n,k) ((n>>k)&1)
#define lg length()
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
typedef long double ld;
typedef pair<int,int>Pin;
typedef pair<ll,ll>Pll;
template<class T> using V=vector<T>;
template<typename T> using min_priority_queue = priority_queue<T, vector<T>, greater<T> >;
long long GCD(long long a, long long b) {return b?GCD(b,a%b):a;}
long long LCM(long long a, long long b) {return a/GCD(a,b)*b;}
ll pom(ll a,ll n,int m){ll x=1;for(a%=m;n;n/=2)n&1?x=x*a%m:0,a=a*a%m;return x;}
#define invp(a,p)pom(a,p-2,p)
int dx[4]={-1,0,1,0};
int dy[4]={0,-1,0,1};
int ddx[8]={-1,0,1,0,1,1,-1,-1};
int ddy[8]={0,-1,0,1,1,-1,1,-1};
ll cmp1(pair<Pll,ll> a,pair<Pll,ll> b){
        return a.fi.se>b.fi.se;
}
ll cmp2(pair<ll,ll> a,pair<ll,ll> b){
    if(a.fi!=b.fi)
        return  a.se<b.se;
    else
        return a.se>b.se;
}
//----------------------------------------------------------------------
struct mint{
    using ull=unsigned long long int;
    ull v;
    mint(ll vv=0){s(vv%mod+mod);}
    mint& s(ull vv){
        v=vv<mod?vv:vv-mod;
        return *this;
    }
    //オーバーロード
    mint operator-()const{return mint()-*this;}//符号反転
    mint&operator+=(const mint&val){return s(v+val.v);}
    mint&operator-=(const mint&val){return s(v+mod-val.v);}
    mint&operator*=(const mint&val){
        v=ull(v)*val.v%mod;
        return *this;
    }
    mint&operator/=(const mint&val){return *this*=val.inv();}
    mint operator+(const mint&val){return mint(*this)+=val;}
    mint operator-(const mint&val){return mint(*this)-=val;}
    mint operator*(const mint&val){return mint(*this)*=val;}
    mint operator/(const mint&val){return mint(*this)/=val;}
    mint pow(int n)const{
        mint res(1),x(*this);
        while(n){
            if(n&1)res*=x;
            x*=x;
            n>>=1;
        }
        return res;
    }
    mint inv()const{return pow(mod-2);}
    //拡張ユークリッドの互除法
    /* mint inv()const{
        int x,y;
        int g=extgcd(v,mod,x,y);
        assert(g==1);
        if(x<0)x+=mod;
        return mint(x);
    }*/
    friend ostream& operator<<(ostream&os,const mint&val){
        return os<<val.v;
    }//出力
    bool operator<(const mint&val)const{return v<val.v;}
    bool operator==(const mint&val)const{return v==val.v;}
    bool operator>(const mint&val)const{return v>val.v;}
};
const ll MAX = 2000010;//設定
mint fac[MAX], finv[MAX], inv[MAX];
// テーブルを作る前処理
void init(){
    fac[0] = fac[1] = 1;
    for(int i=1;i<MAX;i++)fac[i]=fac[i-1]*i;
    finv[MAX-1]=fac[MAX-1].inv();
    for(int i=MAX-2;i>=0;i--)finv[i]=finv[i+1]*(i+1);
    for(int i=MAX-2;i>=1;i--)inv[i]=finv[i]+fac[i-1];
}
//階乗
mint factor(ll n,ll k){
  if (n<k) return 0;
  if (n<0 || k<0) return 0;
  return fac[n]*finv[k];
}
// 二項係数計算
mint COM(int n, int k){
    if (n < k) return 0;
    if (n < 0 || k < 0) return 0;
    return fac[n] * finv[k] * finv[n - k];
}
ll modpow(ll a, ll n) {//a^n(MOD)を求める
    ll res = 1;
    while (n > 0) {
        if (n & 1) res = res * a % mod;
        a = a * a % mod;//次の準備
        n >>= 1;
    }
    return res;
}
ll waru(ll a,ll b){
    return a*modpow(b,mod-2)%mod;
}

ll permutation(ll n,ll r)
{
    ll a=1;
    for(ll i=n-r+1;i<=n;i++)
        a*=i;
    return a;
}

ll nCr(ll n, ll r) {
    ll ans = 1;
    for (ll i = n; i > n - r; --i) {
        ans = ans*i;
    }
    for (ll i = 1 ; i < r + 1; ++i) {
        ans = ans / i;
    }
    return ans;
}

int num = 1;
vector<pair<mint,mint>> A;  // first: 値, second: 遅延評価値
vector<bool> lazyFlag;  // 遅延ありかどうか
const long long INF = 1LL << 60;

// ノード番号 k を遅延評価する (A.at(k).first を正しい値に)
void eval(int k, int l, int r) {
  if (lazyFlag.at(k)) {
    A.at(k).first = A.at(k).second;
    if (r - l > 1) {
      A.at(2*k+1).second = A.at(2*k+2).second = A.at(k).second / 2;
      lazyFlag.at(2*k+1) = lazyFlag.at(2*k+2) = lazyFlag.at(k);
    }
    lazyFlag.at(k) = false;
  }
}

// [a, b) の要素を x に更新
// ノード番号 k は [l, r) に対応している
void update(int a, int b, mint x, int k, int l, int r) {
  eval(k, l, r);
  // [a, b) と [l, r) が交差していない
  if (r <= a || b <= l) return;
  // [a, b) が [l, r) を完全に含む
  if (a <= l && r <= b) {
    A.at(k).second = x * (r - l);
    lazyFlag.at(k) = true;
    eval(k, l, r);
  }
  else {
    update(a, b, x, 2*k+1, l, (l+r)/2);
    update(a, b, x, 2*k+2, (l+r)/2, r);
    A.at(k).first = A.at(2*k+1).first + A.at(2*k+2).first;
  }
}
// [a, b) の合計値を返す
mint getSum(int a, int b, int k, int l, int r) {
  eval(k, l, r);
  if (r <= a || b <= l) return 0;
  if (a <= l && r <= b) return A.at(k).first;
  else {
    mint c1 = getSum(a, b, 2*k+1, l, (l+r)/2);
    mint c2 = getSum(a, b, 2*k+2, (l+r)/2, r);
    return (c1 + c2);
  }
}
//----------------------------------------------------------------------
int main(int argc, char * argv[]){
    cin.tie(0);
    ios::sync_with_stdio(false);
    //-------------------------------  
    //ll begin_t=clock();
    //freopen("big.txt", "r", stdin);
    //freopen("out3.txt", "w", stdout);
    //------------------------------
    ll n;cin>>n;
    V<ll>m(n);
    V<V<ll>>M(n);
    V<ll>all;
    for(ll i=0;i<n;i++){
        cin>>m[i];
        for(ll j=0;j<m[i];j++){
            ll t;cin>>t;
            M[i].pb(t);
            all.pb(t);
        }
        sort(all(M[i]));
        reverse(all(M[i]));
    }
    sort(all(all));
    map<ll,ll>MA;
    ll cnt=0;
    MA[all[0]]=cnt++;
    for(ll i=1;i<all.size();i++){
        if(all[i]!=all[i-1]){
            MA[all[i]]=cnt++;
        }
    }
    for(ll i=0;i<n;i++){
        for(ll j=0;j<m[i];j++){
            M[i][j]=MA[M[i][j]];
        }
    }
    mint ans=1;
    num = 1;
    while (num < 200010) num *= 2;  // 要素数は 2 のべき乗にする
    // 要素数 n のときに必要なノード数は 2*n - 1
    A = vector<pair<mint,mint>>(2*num - 1, make_pair(0, 0));
    lazyFlag = vector<bool>(2*num - 1, false);

    for(ll i=0;i<n;i++){
        for(ll j=0;j<m[i];j++){
            mint tmp =getSum(0,M[i][j],0,0,num);
            ans+=tmp+1;
            update(M[i][j],M[i][j]+1,tmp+1+getSum(M[i][j],M[i][j]+1,0,0,num),0,0,num);
        }
    }

    cout<<ans<<endl;
    //------------------------------
    //fclose(stdin);
    //fclose(stdout);
    //ll end_t=clock();cout<<"time="<<end_t-begin_t<<"ms"<<endl;
    //------------------------------- 
    return 0;
}
//----------------------------------------------------------------------
accuracy: 1
time_ms: 170
memory_kb: 68480
final_rank: 14

code_snippet: #pragma GCC optimize ("O3")
#include <iostream>
#include <iomanip>
#include <istream>
#include <ostream>
#include <sstream>
#include <iterator>
#include <vector>
#include <algorithm>
#include <queue>
#include <deque>
#include <list>
#include <stack>
#include <map>
#include <unordered_map>
#include <set>
#include <bitset>
#include <utility>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <string>
#include <ctime>
#include <cctype>
#include <cstdlib>
#include <numeric>
#define IINF 1000000000
//#define INF 3223372036854775807
#define MOD 1000000007
#define mod 1000000007
#define INT_MAX_ 2147483647
#define EPS (1e-10)
#define REP(i, a, n) fo-r (ll i = a; i < (ll)(n); i++)
#define REPE(i, a, n) for (ll i = a; i <= (ll)(n); i++)
//#define rep(i,n)for (ll i = 0; i < (ll)(n); i++)
#define rep(i,l,r)for(ll i=(l);i<(r);i++)
#define rep1(i,n) for(int i=1;i<=(int)(n);i++)
#define Endl endl
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define eb emplace_back
#define mmax(x,y)(x>y?x:y)
#define mmin(x,y)(x<y?x:y)
#define chmax(x,y) x=mmax(x,y)
#define chmin(x,y) x=mmin(x,y)
#define all(x) (x).begin(),(x).end()
#define siz(x) (ll)(x).size()
#define PI acos(-1.0)
#define me memset
#define bit(n,k) ((n>>k)&1)
#define lg length()
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
typedef long double ld;
typedef pair<int,int>Pin;
typedef pair<ll,ll>Pll;
template<class T> using V=vector<T>;
template<typename T> using min_priority_queue = priority_queue<T, vector<T>, greater<T> >;
long long GCD(long long a, long long b) {return b?GCD(b,a%b):a;}
long long LCM(long long a, long long b) {return a/GCD(a,b)*b;}
ll pom(ll a,ll n,int m){ll x=1;for(a%=m;n;n/=2)n&1?x=x*a%m:0,a=a*a%m;return x;}
#define invp(a,p)pom(a,p-2,p)
int dx[4]={-1,0,1,0};
int dy[4]={0,-1,0,1};
int ddx[8]={-1,0,1,0,1,1,-1,-1};
int ddy[8]={0,-1,0,1,1,-1,1,-1};
ll cmp1(pair<Pll,ll> a,pair<Pll,ll> b){
        return a.fi.se>b.fi.se;
}
ll cmp2(pair<ll,ll> a,pair<ll,ll> b){
    if(a.fi!=b.fi)
        return  a.se<b.se;
    else
        return a.se>b.se;
}
//----------------------------------------------------------------------
struct mint{
    using ull=unsigned long long int;
    ull v;
    mint(ll vv=0){s(vv%mod+mod);}
    mint& s(ull vv){
        v=vv<mod?vv:vv-mod;
        return *this;
    }
    //オーバーロード
    mint operator-()const{return mint()-*this;}//符号反転
    mint&operator+=(const mint&val){return s(v+val.v);}
    mint&operator-=(const mint&val){return s(v+mod-val.v);}
    mint&operator*=(const mint&val){
        v=ull(v)*val.v%mod;
        return *this;
    }
    mint&operator/=(const mint&val){return *this*=val.inv();}
    mint operator+(const mint&val){return mint(*this)+=val;}
    mint operator-(const mint&val){return mint(*this)-=val;}
    mint operator*(const mint&val){return mint(*this)*=val;}
    mint operator/(const mint&val){return mint(*this)/=val;}
    mint pow(int n)const{
        mint res(1),x(*this);
        while(n){
            if(n&1)res*=x;
            x*=x;
            n>>=1;
        }
        return res;
    }
    mint inv()const{return pow(mod-2);}
    //拡張ユークリッドの互除法
    /* mint inv()const{
        int x,y;
        int g=extgcd(v,mod,x,y);
        assert(g==1);
        if(x<0)x+=mod;
        return mint(x);
    }*/
    friend ostream& operator<<(ostream&os,const mint&val){
        return os<<val.v;
    }//出力
    bool operator<(const mint&val)const{return v<val.v;}
    bool operator==(const mint&val)const{return v==val.v;}
    bool operator>(const mint&val)const{return v>val.v;}
};
const ll MAX = 2000010;//設定
mint fac[MAX], finv[MAX], inv[MAX];
// テーブルを作る前処理
void init(){
    fac[0] = fac[1] = 1;
    for(int i=1;i<MAX;i++)fac[i]=fac[i-1]*i;
    finv[MAX-1]=fac[MAX-1].inv();
    for(int i=MAX-2;i>=0;i--)finv[i]=finv[i+1]*(i+1);
    for(int i=MAX-2;i>=1;i--)inv[i]=finv[i]+fac[i-1];
}
//階乗
mint factor(ll n,ll k){
  if (n<k) return 0;
  if (n<0 || k<0) return 0;
  return fac[n]*finv[k];
}
// 二項係数計算
mint COM(int n, int k){
    if (n < k) return 0;
    if (n < 0 || k < 0) return 0;
    return fac[n] * finv[k] * finv[n - k];
}
ll modpow(ll a, ll n) {//a^n(MOD)を求める
    ll res = 1;
    while (n > 0) {
        if (n & 1) res = res * a % mod;
        a = a * a % mod;//次の準備
        n >>= 1;
    }
    return res;
}
ll waru(ll a,ll b){
    return a*modpow(b,mod-2)%mod;
}

ll permutation(ll n,ll r)
{
    ll a=1;
    for(ll i=n-r+1;i<=n;i++)
        a*=i;
    return a;
}

ll nCr(ll n, ll r) {
    ll ans = 1;
    for (ll i = n; i > n - r; --i) {
        ans = ans*i;
    }
    for (ll i = 1 ; i < r + 1; ++i) {
        ans = ans / i;
    }
    return ans;
}

int num = 1;
vector<pair<mint,mint>> A;  // first: 値, second: 遅延評価値
vector<bool> lazyFlag;  // 遅延ありかどうか
const long long INF = 1LL << 60;

// ノード番号 k を遅延評価する (A.at(k).first を正しい値に)
void eval(int k, int l, int r) {
  if (lazyFlag.at(k)) {
    A.at(k).first = A.at(k).second;
    if (r - l > 1) {
      A.at(2*k+1).second = A.at(2*k+2).second = A.at(k).second / 2;
      lazyFlag.at(2*k+1) = lazyFlag.at(2*k+2) = lazyFlag.at(k);
    }
    lazyFlag.at(k) = false;
  }
}

// [a, b) の要素を x に更新
// ノード番号 k は [l, r) に対応している
void update(int a, int b, mint x, int k, int l, int r) {
  eval(k, l, r);
  // [a, b) と [l, r) が交差していない
  if (r <= a || b <= l) return;
  // [a, b) が [l, r) を完全に含む
  if (a <= l && r <= b) {
    A.at(k).second = x * (r - l);
    lazyFlag.at(k) = true;
    eval(k, l, r);
  }
  else {
    update(a, b, x, 2*k+1, l, (l+r)/2);
    update(a, b, x, 2*k+2, (l+r)/2, r);
    A.at(k).first = A.at(2*k+1).first + A.at(2*k+2).first;
  }
}
// [a, b) の合計値を返す
mint getSum(int a, int b, int k, int l, int r) {
  eval(k, l, r);
  if (r <= a || b <= l) return 0;
  if (a <= l && r <= b) return A.at(k).first;
  else {
    mint c1 = getSum(a, b, 2*k+1, l, (l+r)/2);
    mint c2 = getSum(a, b, 2*k+2, (l+r)/2, r);
    return (c1 + c2);
  }
}
//----------------------------------------------------------------------
int main(int argc, char * argv[]){
    cin.tie(0);
    ios::sync_with_stdio(false);
    //-------------------------------  
    //ll begin_t=clock();
    //freopen("big.txt", "r", stdin);
    //freopen("out3.txt", "w", stdout);
    //------------------------------
    ll n;cin>>n;
    V<ll>m(n);
    V<V<ll>>M(n);
    V<ll>all;
    for(ll i=0;i<n;i++){
        cin>>m[i];
        for(ll j=0;j<m[i];j++){
            ll t;cin>>t;
            M[i].pb(t);
            all.pb(t);
        }
        sort(all(M[i]));
        reverse(all(M[i]));
    }
    sort(all(all));
    map<ll,ll>MA;
    ll cnt=0;
    MA[all[0]]=cnt++;
    for(ll i=1;i<all.size();i++){
        if(all[i]!=all[i-1]){
            MA[all[i]]=cnt++;
        }
    }
    for(ll i=0;i<n;i++){
        for(ll j=0;j<m[i];j++){
            M[i][j]=MA[M[i][j]];
        }
    }
    mint ans=1;
    num = 1;
    while (num < 200010) num *= 2;  // 要素数は 2 のべき乗にする
    // 要素数 n のときに必要なノード数は 2*n - 1
    A = vector<pair<mint,mint>>(2*num - 1, make_pair(0, 0));
    lazyFlag = vector<bool>(2*num - 1, false);

    for(ll i=0;i<n;i++){
        for(ll j=0;j<m[i];j++){
            mint tmp =getSum(0,M[i][j],0,0,num);
            ans+=tmp+1;
            update(M[i][j],M[i][j]+1,tmp+1,0,0,num);
        }
    }

    cout<<ans<<endl;
    //------------------------------
    //fclose(stdin);
    //fclose(stdout);
    //ll end_t=clock();cout<<"time="<<end_t-begin_t<<"ms"<<endl;
    //------------------------------- 
    return 0;
}
//----------------------------------------------------------------------
accuracy: 0.3181818181818182
time_ms: 140
memory_kb: 68360
final_rank: 20

code_snippet: #pragma GCC optimize ("O3")
#include <iostream>
#include <iomanip>
#include <istream>
#include <ostream>
#include <sstream>
#include <iterator>
#include <vector>
#include <algorithm>
#include <queue>
#include <deque>
#include <list>
#include <stack>
#include <map>
#include <unordered_map>
#include <set>
#include <bitset>
#include <utility>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <string>
#include <ctime>
#include <cctype>
#include <cstdlib>
#include <numeric>
#define IINF 1000000000
//#define INF 3223372036854775807
#define MOD 1000000007
#define mod 1000000007
#define INT_MAX_ 2147483647
#define EPS (1e-10)
#define REP(i, a, n) fo-r (ll i = a; i < (ll)(n); i++)
#define REPE(i, a, n) for (ll i = a; i <= (ll)(n); i++)
//#define rep(i,n)for (ll i = 0; i < (ll)(n); i++)
#define rep(i,l,r)for(ll i=(l);i<(r);i++)
#define rep1(i,n) for(int i=1;i<=(int)(n);i++)
#define Endl endl
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define eb emplace_back
#define mmax(x,y)(x>y?x:y)
#define mmin(x,y)(x<y?x:y)
#define chmax(x,y) x=mmax(x,y)
#define chmin(x,y) x=mmin(x,y)
#define all(x) (x).begin(),(x).end()
#define siz(x) (ll)(x).size()
#define PI acos(-1.0)
#define me memset
#define bit(n,k) ((n>>k)&1)
#define lg length()
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
typedef long double ld;
typedef pair<int,int>Pin;
typedef pair<ll,ll>Pll;
template<class T> using V=vector<T>;
template<typename T> using min_priority_queue = priority_queue<T, vector<T>, greater<T> >;
long long GCD(long long a, long long b) {return b?GCD(b,a%b):a;}
long long LCM(long long a, long long b) {return a/GCD(a,b)*b;}
ll pom(ll a,ll n,int m){ll x=1;for(a%=m;n;n/=2)n&1?x=x*a%m:0,a=a*a%m;return x;}
#define invp(a,p)pom(a,p-2,p)
int dx[4]={-1,0,1,0};
int dy[4]={0,-1,0,1};
int ddx[8]={-1,0,1,0,1,1,-1,-1};
int ddy[8]={0,-1,0,1,1,-1,1,-1};
ll cmp1(pair<Pll,ll> a,pair<Pll,ll> b){
        return a.fi.se>b.fi.se;
}
ll cmp2(pair<ll,ll> a,pair<ll,ll> b){
    if(a.fi!=b.fi)
        return  a.se<b.se;
    else
        return a.se>b.se;
}
//----------------------------------------------------------------------
struct mint{
    using ull=unsigned long long int;
    ull v;
    mint(ll vv=0){s(vv%mod+mod);}
    mint& s(ull vv){
        v=vv<mod?vv:vv-mod;
        return *this;
    }
    //オーバーロード
    mint operator-()const{return mint()-*this;}//符号反転
    mint&operator+=(const mint&val){return s(v+val.v);}
    mint&operator-=(const mint&val){return s(v+mod-val.v);}
    mint&operator*=(const mint&val){
        v=ull(v)*val.v%mod;
        return *this;
    }
    mint&operator/=(const mint&val){return *this*=val.inv();}
    mint operator+(const mint&val){return mint(*this)+=val;}
    mint operator-(const mint&val){return mint(*this)-=val;}
    mint operator*(const mint&val){return mint(*this)*=val;}
    mint operator/(const mint&val){return mint(*this)/=val;}
    mint pow(int n)const{
        mint res(1),x(*this);
        while(n){
            if(n&1)res*=x;
            x*=x;
            n>>=1;
        }
        return res;
    }
    mint inv()const{return pow(mod-2);}
    //拡張ユークリッドの互除法
    /* mint inv()const{
        int x,y;
        int g=extgcd(v,mod,x,y);
        assert(g==1);
        if(x<0)x+=mod;
        return mint(x);
    }*/
    friend ostream& operator<<(ostream&os,const mint&val){
        return os<<val.v;
    }//出力
    bool operator<(const mint&val)const{return v<val.v;}
    bool operator==(const mint&val)const{return v==val.v;}
    bool operator>(const mint&val)const{return v>val.v;}
};
const ll MAX = 2000010;//設定
mint fac[MAX], finv[MAX], inv[MAX];
// テーブルを作る前処理
void init(){
    fac[0] = fac[1] = 1;
    for(int i=1;i<MAX;i++)fac[i]=fac[i-1]*i;
    finv[MAX-1]=fac[MAX-1].inv();
    for(int i=MAX-2;i>=0;i--)finv[i]=finv[i+1]*(i+1);
    for(int i=MAX-2;i>=1;i--)inv[i]=finv[i]+fac[i-1];
}
//階乗
mint factor(ll n,ll k){
  if (n<k) return 0;
  if (n<0 || k<0) return 0;
  return fac[n]*finv[k];
}
// 二項係数計算
mint COM(int n, int k){
    if (n < k) return 0;
    if (n < 0 || k < 0) return 0;
    return fac[n] * finv[k] * finv[n - k];
}
ll modpow(ll a, ll n) {//a^n(MOD)を求める
    ll res = 1;
    while (n > 0) {
        if (n & 1) res = res * a % mod;
        a = a * a % mod;//次の準備
        n >>= 1;
    }
    return res;
}
ll waru(ll a,ll b){
    return a*modpow(b,mod-2)%mod;
}

ll permutation(ll n,ll r)
{
    ll a=1;
    for(ll i=n-r+1;i<=n;i++)
        a*=i;
    return a;
}

ll nCr(ll n, ll r) {
    ll ans = 1;
    for (ll i = n; i > n - r; --i) {
        ans = ans*i;
    }
    for (ll i = 1 ; i < r + 1; ++i) {
        ans = ans / i;
    }
    return ans;
}

int num = 1;
vector<Pll> A;  // first: 値, second: 遅延評価値
vector<bool> lazyFlag;  // 遅延ありかどうか
const long long INF = 1LL << 60;

// ノード番号 k を遅延評価する (A.at(k).first を正しい値に)
void eval(int k, int l, int r) {
  if (lazyFlag.at(k)) {
    A.at(k).first = A.at(k).second;
    if (r - l > 1) {
      A.at(2*k+1).second = A.at(2*k+2).second = A.at(k).second / 2;
      lazyFlag.at(2*k+1) = lazyFlag.at(2*k+2) = lazyFlag.at(k);
    }
    lazyFlag.at(k) = false;
  }
}

// [a, b) の要素を x に更新
// ノード番号 k は [l, r) に対応している
void update(int a, int b, int x, int k, int l, int r) {
  eval(k, l, r);
  // [a, b) と [l, r) が交差していない
  if (r <= a || b <= l) return;
  // [a, b) が [l, r) を完全に含む
  if (a <= l && r <= b) {
    A.at(k).second = x * (r - l);
    lazyFlag.at(k) = true;
    eval(k, l, r);
  }
  else {
    update(a, b, x, 2*k+1, l, (l+r)/2);
    update(a, b, x, 2*k+2, (l+r)/2, r);
    A.at(k).first = A.at(2*k+1).first + A.at(2*k+2).first;
  }
}
/*
void update(int a, int b, T x) {
    update(a, b, x, 0, 0, n);
}*/
// [a, b) の合計値を返す
long long getSum(int a, int b, int k, int l, int r) {
  eval(k, l, r);
  if (r <= a || b <= l) return 0;
  if (a <= l && r <= b) return A.at(k).first%mod;
  else {
    long long c1 = getSum(a, b, 2*k+1, l, (l+r)/2);
    long long c2 = getSum(a, b, 2*k+2, (l+r)/2, r);
    return (c1 + c2)%mod;
  }/*
  T getSum(int a, int b) {
        return getSum(a, b, 0, 0, n);
    }*/
}
//----------------------------------------------------------------------
int main(int argc, char * argv[]){
    cin.tie(0);
    ios::sync_with_stdio(false);
    //-------------------------------  
    //ll begin_t=clock();
    //freopen("big.txt", "r", stdin);
    //freopen("out3.txt", "w", stdout);
    //------------------------------
    ll n;cin>>n;
    V<ll>m(n);
    V<V<ll>>M(n);
    V<ll>all;
    for(ll i=0;i<n;i++){
        cin>>m[i];
        for(ll j=0;j<m[i];j++){
            ll t;cin>>t;
            M[i].pb(t);
            all.pb(t);
        }
        sort(all(M[i]));
        reverse(all(M[i]));
    }
    sort(all(all));
    map<ll,ll>MA;
    ll cnt=0;
    MA[all[0]]=cnt++;
    for(ll i=1;i<all.size();i++){
        if(all[i]!=all[i-1]){
            MA[all[i]]=cnt++;
        }
    }
    for(ll i=0;i<n;i++){
        for(ll j=0;j<m[i];j++){
            M[i][j]=MA[M[i][j]];
        }
    }
    mint ans=1;
    num = 1;
    while (num < 200010) num *= 2;  // 要素数は 2 のべき乗にする
    // 要素数 n のときに必要なノード数は 2*n - 1
    A = vector<Pll>(2*num - 1, make_pair(0, 0));
    lazyFlag = vector<bool>(2*num - 1, false);

    for(ll i=0;i<n;i++){
        for(ll j=0;j<m[i];j++){
            ll tmp =getSum(0,M[i][j],0,0,num);
            ans+=tmp%mod+1;
            update(M[i][j],M[i][j]+1,tmp%mod+1,0,0,num);
        }
    }

    cout<<ans<<endl;
    //------------------------------
    //fclose(stdin);
    //fclose(stdout);
    //ll end_t=clock();cout<<"time="<<end_t-begin_t<<"ms"<<endl;
    //------------------------------- 
    return 0;
}
//----------------------------------------------------------------------
accuracy: 0.3181818181818182
time_ms: 130
memory_kb: 68136
final_rank: 18

code_snippet: #pragma GCC optimize ("O3")
#include <iostream>
#include <iomanip>
#include <istream>
#include <ostream>
#include <sstream>
#include <iterator>
#include <vector>
#include <algorithm>
#include <queue>
#include <deque>
#include <list>
#include <stack>
#include <map>
#include <unordered_map>
#include <set>
#include <bitset>
#include <utility>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <string>
#include <ctime>
#include <cctype>
#include <cstdlib>
#include <numeric>
#define IINF 1000000000
//#define INF 3223372036854775807
#define MOD 1000000007
#define mod 1000000007
#define INT_MAX_ 2147483647
#define EPS (1e-10)
#define REP(i, a, n) fo-r (ll i = a; i < (ll)(n); i++)
#define REPE(i, a, n) for (ll i = a; i <= (ll)(n); i++)
//#define rep(i,n)for (ll i = 0; i < (ll)(n); i++)
#define rep(i,l,r)for(ll i=(l);i<(r);i++)
#define rep1(i,n) for(int i=1;i<=(int)(n);i++)
#define Endl endl
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define eb emplace_back
#define mmax(x,y)(x>y?x:y)
#define mmin(x,y)(x<y?x:y)
#define chmax(x,y) x=mmax(x,y)
#define chmin(x,y) x=mmin(x,y)
#define all(x) (x).begin(),(x).end()
#define siz(x) (ll)(x).size()
#define PI acos(-1.0)
#define me memset
#define bit(n,k) ((n>>k)&1)
#define lg length()
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
typedef long double ld;
typedef pair<int,int>Pin;
typedef pair<ll,ll>Pll;
template<class T> using V=vector<T>;
template<typename T> using min_priority_queue = priority_queue<T, vector<T>, greater<T> >;
long long GCD(long long a, long long b) {return b?GCD(b,a%b):a;}
long long LCM(long long a, long long b) {return a/GCD(a,b)*b;}
ll pom(ll a,ll n,int m){ll x=1;for(a%=m;n;n/=2)n&1?x=x*a%m:0,a=a*a%m;return x;}
#define invp(a,p)pom(a,p-2,p)
int dx[4]={-1,0,1,0};
int dy[4]={0,-1,0,1};
int ddx[8]={-1,0,1,0,1,1,-1,-1};
int ddy[8]={0,-1,0,1,1,-1,1,-1};
ll cmp1(pair<Pll,ll> a,pair<Pll,ll> b){
        return a.fi.se>b.fi.se;
}
ll cmp2(pair<ll,ll> a,pair<ll,ll> b){
    if(a.fi!=b.fi)
        return  a.se<b.se;
    else
        return a.se>b.se;
}
//----------------------------------------------------------------------
struct mint{
    using ull=unsigned long long int;
    ull v;
    mint(ll vv=0){s(vv%mod+mod);}
    mint& s(ull vv){
        v=vv<mod?vv:vv-mod;
        return *this;
    }
    //オーバーロード
    mint operator-()const{return mint()-*this;}//符号反転
    mint&operator+=(const mint&val){return s(v+val.v);}
    mint&operator-=(const mint&val){return s(v+mod-val.v);}
    mint&operator*=(const mint&val){
        v=ull(v)*val.v%mod;
        return *this;
    }
    mint&operator/=(const mint&val){return *this*=val.inv();}
    mint operator+(const mint&val){return mint(*this)+=val;}
    mint operator-(const mint&val){return mint(*this)-=val;}
    mint operator*(const mint&val){return mint(*this)*=val;}
    mint operator/(const mint&val){return mint(*this)/=val;}
    mint pow(int n)const{
        mint res(1),x(*this);
        while(n){
            if(n&1)res*=x;
            x*=x;
            n>>=1;
        }
        return res;
    }
    mint inv()const{return pow(mod-2);}
    //拡張ユークリッドの互除法
    /* mint inv()const{
        int x,y;
        int g=extgcd(v,mod,x,y);
        assert(g==1);
        if(x<0)x+=mod;
        return mint(x);
    }*/
    friend ostream& operator<<(ostream&os,const mint&val){
        return os<<val.v;
    }//出力
    bool operator<(const mint&val)const{return v<val.v;}
    bool operator==(const mint&val)const{return v==val.v;}
    bool operator>(const mint&val)const{return v>val.v;}
};
const ll MAX = 2000010;//設定
mint fac[MAX], finv[MAX], inv[MAX];
// テーブルを作る前処理
void init(){
    fac[0] = fac[1] = 1;
    for(int i=1;i<MAX;i++)fac[i]=fac[i-1]*i;
    finv[MAX-1]=fac[MAX-1].inv();
    for(int i=MAX-2;i>=0;i--)finv[i]=finv[i+1]*(i+1);
    for(int i=MAX-2;i>=1;i--)inv[i]=finv[i]+fac[i-1];
}
//階乗
mint factor(ll n,ll k){
  if (n<k) return 0;
  if (n<0 || k<0) return 0;
  return fac[n]*finv[k];
}
// 二項係数計算
mint COM(int n, int k){
    if (n < k) return 0;
    if (n < 0 || k < 0) return 0;
    return fac[n] * finv[k] * finv[n - k];
}
ll modpow(ll a, ll n) {//a^n(MOD)を求める
    ll res = 1;
    while (n > 0) {
        if (n & 1) res = res * a % mod;
        a = a * a % mod;//次の準備
        n >>= 1;
    }
    return res;
}
ll waru(ll a,ll b){
    return a*modpow(b,mod-2)%mod;
}

ll permutation(ll n,ll r)
{
    ll a=1;
    for(ll i=n-r+1;i<=n;i++)
        a*=i;
    return a;
}

ll nCr(ll n, ll r) {
    ll ans = 1;
    for (ll i = n; i > n - r; --i) {
        ans = ans*i;
    }
    for (ll i = 1 ; i < r + 1; ++i) {
        ans = ans / i;
    }
    return ans;
}

int num = 1;
vector<Pll> A;  // first: 値, second: 遅延評価値
vector<bool> lazyFlag;  // 遅延ありかどうか
const long long INF = 1LL << 60;

// ノード番号 k を遅延評価する (A.at(k).first を正しい値に)
void eval(int k, int l, int r) {
  if (lazyFlag.at(k)) {
    A.at(k).first = A.at(k).second;
    if (r - l > 1) {
      A.at(2*k+1).second = A.at(2*k+2).second = A.at(k).second / 2;
      lazyFlag.at(2*k+1) = lazyFlag.at(2*k+2) = lazyFlag.at(k);
    }
    lazyFlag.at(k) = false;
  }
}

// [a, b) の要素を x に更新
// ノード番号 k は [l, r) に対応している
void update(int a, int b, int x, int k, int l, int r) {
  eval(k, l, r);
  // [a, b) と [l, r) が交差していない
  if (r <= a || b <= l) return;
  // [a, b) が [l, r) を完全に含む
  if (a <= l && r <= b) {
    A.at(k).second = x * (r - l);
    lazyFlag.at(k) = true;
    eval(k, l, r);
  }
  else {
    update(a, b, x, 2*k+1, l, (l+r)/2);
    update(a, b, x, 2*k+2, (l+r)/2, r);
    A.at(k).first = A.at(2*k+1).first + A.at(2*k+2).first;
  }
}
/*
void update(int a, int b, T x) {
    update(a, b, x, 0, 0, n);
}*/
// [a, b) の合計値を返す
long long getSum(int a, int b, int k, int l, int r) {
  eval(k, l, r);
  if (r <= a || b <= l) return 0;
  if (a <= l && r <= b) return A.at(k).first;
  else {
    long long c1 = getSum(a, b, 2*k+1, l, (l+r)/2);
    long long c2 = getSum(a, b, 2*k+2, (l+r)/2, r);
    return (c1 + c2)%mod;
  }/*
  T getSum(int a, int b) {
        return getSum(a, b, 0, 0, n);
    }*/
}

bool color[100010];
//----------------------------------------------------------------------
int main(int argc, char * argv[]){
    cin.tie(0);
    ios::sync_with_stdio(false);
    //-------------------------------  
    //ll begin_t=clock();
    //freopen("big.txt", "r", stdin);
    //freopen("out3.txt", "w", stdout);
    //------------------------------
    ll n;cin>>n;
    V<ll>m(n);
    V<V<ll>>M(n);
    V<ll>all;
    for(ll i=0;i<n;i++){
        cin>>m[i];
        for(ll j=0;j<m[i];j++){
            ll t;cin>>t;
            M[i].pb(t);
            all.pb(t);
        }
        sort(all(M[i]));
        reverse(all(M[i]));
    }
    sort(all(all));
    map<ll,ll>MA;
    ll cnt=0;
    MA[all[0]]=cnt++;
    for(ll i=1;i<all.size();i++){
        if(all[i]!=all[i-1]){
            MA[all[i]]=cnt++;
        }
    }
    for(ll i=0;i<n;i++){
        for(ll j=0;j<m[i];j++){
            M[i][j]=MA[M[i][j]];
        }
    }
    mint ans=1;
    num = 1;
    while (num < 200010) num *= 2;  // 要素数は 2 のべき乗にする
    // 要素数 n のときに必要なノード数は 2*n - 1
    A = vector<Pll>(2*num - 1, make_pair(0, 0));
    lazyFlag = vector<bool>(2*num - 1, false);

    for(ll i=0;i<n;i++){
        for(ll j=0;j<m[i];j++){
            ll tmp =getSum(0,M[i][j],0,0,num);
            ans+=tmp+1;
            update(M[i][j],M[i][j]+1,tmp+1,0,0,num);
        }
    }

    cout<<ans<<endl;
    //------------------------------
    //fclose(stdin);
    //fclose(stdout);
    //ll end_t=clock();cout<<"time="<<end_t-begin_t<<"ms"<<endl;
    //------------------------------- 
    return 0;
}
//----------------------------------------------------------------------
accuracy: 0.3181818181818182
time_ms: 120
memory_kb: 68236
final_rank: 16

code_snippet: #pragma GCC optimize ("O3")
#include <iostream>
#include <iomanip>
#include <istream>
#include <ostream>
#include <sstream>
#include <iterator>
#include <vector>
#include <algorithm>
#include <queue>
#include <deque>
#include <list>
#include <stack>
#include <map>
#include <unordered_map>
#include <set>
#include <bitset>
#include <utility>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <string>
#include <ctime>
#include <cctype>
#include <cstdlib>
#include <numeric>
#define IINF 1000000000
//#define INF 3223372036854775807
#define MOD 1000000007
#define mod 1000000007
#define INT_MAX_ 2147483647
#define EPS (1e-10)
#define REP(i, a, n) fo-r (ll i = a; i < (ll)(n); i++)
#define REPE(i, a, n) for (ll i = a; i <= (ll)(n); i++)
//#define rep(i,n)for (ll i = 0; i < (ll)(n); i++)
#define rep(i,l,r)for(ll i=(l);i<(r);i++)
#define rep1(i,n) for(int i=1;i<=(int)(n);i++)
#define Endl endl
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define eb emplace_back
#define mmax(x,y)(x>y?x:y)
#define mmin(x,y)(x<y?x:y)
#define chmax(x,y) x=mmax(x,y)
#define chmin(x,y) x=mmin(x,y)
#define all(x) (x).begin(),(x).end()
#define siz(x) (ll)(x).size()
#define PI acos(-1.0)
#define me memset
#define bit(n,k) ((n>>k)&1)
#define lg length()
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
typedef long double ld;
typedef pair<int,int>Pin;
typedef pair<ll,ll>Pll;
template<class T> using V=vector<T>;
template<typename T> using min_priority_queue = priority_queue<T, vector<T>, greater<T> >;
long long GCD(long long a, long long b) {return b?GCD(b,a%b):a;}
long long LCM(long long a, long long b) {return a/GCD(a,b)*b;}
ll pom(ll a,ll n,int m){ll x=1;for(a%=m;n;n/=2)n&1?x=x*a%m:0,a=a*a%m;return x;}
#define invp(a,p)pom(a,p-2,p)
int dx[4]={-1,0,1,0};
int dy[4]={0,-1,0,1};
int ddx[8]={-1,0,1,0,1,1,-1,-1};
int ddy[8]={0,-1,0,1,1,-1,1,-1};
ll cmp1(pair<Pll,ll> a,pair<Pll,ll> b){
        return a.fi.se>b.fi.se;
}
ll cmp2(pair<ll,ll> a,pair<ll,ll> b){
    if(a.fi!=b.fi)
        return  a.se<b.se;
    else
        return a.se>b.se;
}
//----------------------------------------------------------------------
struct mint{
    using ull=unsigned long long int;
    ull v;
    mint(ll vv=0){s(vv%mod+mod);}
    mint& s(ull vv){
        v=vv<mod?vv:vv-mod;
        return *this;
    }
    //オーバーロード
    mint operator-()const{return mint()-*this;}//符号反転
    mint&operator+=(const mint&val){return s(v+val.v);}
    mint&operator-=(const mint&val){return s(v+mod-val.v);}
    mint&operator*=(const mint&val){
        v=ull(v)*val.v%mod;
        return *this;
    }
    mint&operator/=(const mint&val){return *this*=val.inv();}
    mint operator+(const mint&val){return mint(*this)+=val;}
    mint operator-(const mint&val){return mint(*this)-=val;}
    mint operator*(const mint&val){return mint(*this)*=val;}
    mint operator/(const mint&val){return mint(*this)/=val;}
    mint pow(int n)const{
        mint res(1),x(*this);
        while(n){
            if(n&1)res*=x;
            x*=x;
            n>>=1;
        }
        return res;
    }
    mint inv()const{return pow(mod-2);}
    //拡張ユークリッドの互除法
    /* mint inv()const{
        int x,y;
        int g=extgcd(v,mod,x,y);
        assert(g==1);
        if(x<0)x+=mod;
        return mint(x);
    }*/
    friend ostream& operator<<(ostream&os,const mint&val){
        return os<<val.v;
    }//出力
    bool operator<(const mint&val)const{return v<val.v;}
    bool operator==(const mint&val)const{return v==val.v;}
    bool operator>(const mint&val)const{return v>val.v;}
};
const ll MAX = 2000010;//設定
mint fac[MAX], finv[MAX], inv[MAX];
// テーブルを作る前処理
void init(){
    fac[0] = fac[1] = 1;
    for(int i=1;i<MAX;i++)fac[i]=fac[i-1]*i;
    finv[MAX-1]=fac[MAX-1].inv();
    for(int i=MAX-2;i>=0;i--)finv[i]=finv[i+1]*(i+1);
    for(int i=MAX-2;i>=1;i--)inv[i]=finv[i]+fac[i-1];
}
//階乗
mint factor(ll n,ll k){
  if (n<k) return 0;
  if (n<0 || k<0) return 0;
  return fac[n]*finv[k];
}
// 二項係数計算
mint COM(int n, int k){
    if (n < k) return 0;
    if (n < 0 || k < 0) return 0;
    return fac[n] * finv[k] * finv[n - k];
}
ll modpow(ll a, ll n) {//a^n(MOD)を求める
    ll res = 1;
    while (n > 0) {
        if (n & 1) res = res * a % mod;
        a = a * a % mod;//次の準備
        n >>= 1;
    }
    return res;
}
ll waru(ll a,ll b){
    return a*modpow(b,mod-2)%mod;
}

ll permutation(ll n,ll r)
{
    ll a=1;
    for(ll i=n-r+1;i<=n;i++)
        a*=i;
    return a;
}

ll nCr(ll n, ll r) {
    ll ans = 1;
    for (ll i = n; i > n - r; --i) {
        ans = ans*i;
    }
    for (ll i = 1 ; i < r + 1; ++i) {
        ans = ans / i;
    }
    return ans;
}

int num = 1;
vector<Pll> A;  // first: 値, second: 遅延評価値
vector<bool> lazyFlag;  // 遅延ありかどうか
const long long INF = 1LL << 60;

// ノード番号 k を遅延評価する (A.at(k).first を正しい値に)
void eval(int k, int l, int r) {
  if (lazyFlag.at(k)) {
    A.at(k).first = A.at(k).second;
    if (r - l > 1) {
      A.at(2*k+1).second = A.at(2*k+2).second = A.at(k).second / 2;
      lazyFlag.at(2*k+1) = lazyFlag.at(2*k+2) = lazyFlag.at(k);
    }
    lazyFlag.at(k) = false;
  }
}

// [a, b) の要素を x に更新
// ノード番号 k は [l, r) に対応している
void update(int a, int b, int x, int k, int l, int r) {
  eval(k, l, r);
  // [a, b) と [l, r) が交差していない
  if (r <= a || b <= l) return;
  // [a, b) が [l, r) を完全に含む
  if (a <= l && r <= b) {
    A.at(k).second = x * (r - l);
    lazyFlag.at(k) = true;
    eval(k, l, r);
  }
  else {
    update(a, b, x, 2*k+1, l, (l+r)/2);
    update(a, b, x, 2*k+2, (l+r)/2, r);
    A.at(k).first = A.at(2*k+1).first + A.at(2*k+2).first;
  }
}
/*
void update(int a, int b, T x) {
    update(a, b, x, 0, 0, n);
}*/
// [a, b) の合計値を返す
long long getSum(int a, int b, int k, int l, int r) {
  eval(k, l, r);
  if (r <= a || b <= l) return 0;
  if (a <= l && r <= b) return A.at(k).first;
  else {
    long long c1 = getSum(a, b, 2*k+1, l, (l+r)/2);
    long long c2 = getSum(a, b, 2*k+2, (l+r)/2, r);
    return c1 + c2;
  }/*
  T getSum(int a, int b) {
        return getSum(a, b, 0, 0, n);
    }*/
}

bool color[100010];
//----------------------------------------------------------------------
int main(int argc, char * argv[]){
    cin.tie(0);
    ios::sync_with_stdio(false);
    //-------------------------------  
    //ll begin_t=clock();
    //freopen("big.txt", "r", stdin);
    //freopen("out3.txt", "w", stdout);
    //------------------------------
    ll n;cin>>n;
    V<ll>m(n);
    V<V<ll>>M(n);
    V<ll>all;
    for(ll i=0;i<n;i++){
        cin>>m[i];
        for(ll j=0;j<m[i];j++){
            ll t;cin>>t;
            M[i].pb(t);
            all.pb(t);
        }
        sort(all(M[i]));
        reverse(all(M[i]));
    }
    sort(all(all));
    map<ll,ll>MA;
    ll cnt=0;
    MA[all[0]]=cnt++;
    for(ll i=1;i<all.size();i++){
        if(all[i]!=all[i-1]){
            MA[all[i]]=cnt++;
        }
    }
    for(ll i=0;i<n;i++){
        for(ll j=0;j<m[i];j++){
            M[i][j]=MA[M[i][j]];
        }
    }
    mint ans=1;
    num = 1;
    while (num < 200010) num *= 2;  // 要素数は 2 のべき乗にする
    // 要素数 n のときに必要なノード数は 2*n - 1
    A = vector<Pll>(2*num - 1, make_pair(0, 0));
    lazyFlag = vector<bool>(2*num - 1, false);

    for(ll i=0;i<n;i++){
        for(ll j=0;j<m[i];j++){
            ll tmp =getSum(0,M[i][j],0,0,num);
            ans+=tmp+1;
            //if(tmp+1>getSum(M[i][j],M[i][j]+1,0,0,num))
            update(M[i][j],M[i][j]+1,tmp+1,0,0,num);
        }
    }

    cout<<ans<<endl;
    //------------------------------
    //fclose(stdin);
    //fclose(stdout);
    //ll end_t=clock();cout<<"time="<<end_t-begin_t<<"ms"<<endl;
    //------------------------------- 
    return 0;
}
//----------------------------------------------------------------------
accuracy: 0.3181818181818182
time_ms: 130
memory_kb: 68292
final_rank: 19

code_snippet: #pragma GCC optimize ("O3")
#include <iostream>
#include <iomanip>
#include <istream>
#include <ostream>
#include <sstream>
#include <iterator>
#include <vector>
#include <algorithm>
#include <queue>
#include <deque>
#include <list>
#include <stack>
#include <map>
#include <unordered_map>
#include <set>
#include <bitset>
#include <utility>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <string>
#include <ctime>
#include <cctype>
#include <cstdlib>
#include <numeric>
#define IINF 1000000000
//#define INF 3223372036854775807
#define MOD 1000000007
#define mod 1000000007
#define INT_MAX_ 2147483647
#define EPS (1e-10)
#define REP(i, a, n) fo-r (ll i = a; i < (ll)(n); i++)
#define REPE(i, a, n) for (ll i = a; i <= (ll)(n); i++)
//#define rep(i,n)for (ll i = 0; i < (ll)(n); i++)
#define rep(i,l,r)for(ll i=(l);i<(r);i++)
#define rep1(i,n) for(int i=1;i<=(int)(n);i++)
#define Endl endl
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define eb emplace_back
#define mmax(x,y)(x>y?x:y)
#define mmin(x,y)(x<y?x:y)
#define chmax(x,y) x=mmax(x,y)
#define chmin(x,y) x=mmin(x,y)
#define all(x) (x).begin(),(x).end()
#define siz(x) (ll)(x).size()
#define PI acos(-1.0)
#define me memset
#define bit(n,k) ((n>>k)&1)
#define lg length()
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
typedef long double ld;
typedef pair<int,int>Pin;
typedef pair<ll,ll>Pll;
template<class T> using V=vector<T>;
template<typename T> using min_priority_queue = priority_queue<T, vector<T>, greater<T> >;
long long GCD(long long a, long long b) {return b?GCD(b,a%b):a;}
long long LCM(long long a, long long b) {return a/GCD(a,b)*b;}
ll pom(ll a,ll n,int m){ll x=1;for(a%=m;n;n/=2)n&1?x=x*a%m:0,a=a*a%m;return x;}
#define invp(a,p)pom(a,p-2,p)
int dx[4]={-1,0,1,0};
int dy[4]={0,-1,0,1};
int ddx[8]={-1,0,1,0,1,1,-1,-1};
int ddy[8]={0,-1,0,1,1,-1,1,-1};
ll cmp1(pair<Pll,ll> a,pair<Pll,ll> b){
        return a.fi.se>b.fi.se;
}
ll cmp2(pair<ll,ll> a,pair<ll,ll> b){
    if(a.fi!=b.fi)
        return  a.se<b.se;
    else
        return a.se>b.se;
}
//----------------------------------------------------------------------
struct mint{
    using ull=unsigned long long int;
    ull v;
    mint(ll vv=0){s(vv%mod+mod);}
    mint& s(ull vv){
        v=vv<mod?vv:vv-mod;
        return *this;
    }
    //オーバーロード
    mint operator-()const{return mint()-*this;}//符号反転
    mint&operator+=(const mint&val){return s(v+val.v);}
    mint&operator-=(const mint&val){return s(v+mod-val.v);}
    mint&operator*=(const mint&val){
        v=ull(v)*val.v%mod;
        return *this;
    }
    mint&operator/=(const mint&val){return *this*=val.inv();}
    mint operator+(const mint&val){return mint(*this)+=val;}
    mint operator-(const mint&val){return mint(*this)-=val;}
    mint operator*(const mint&val){return mint(*this)*=val;}
    mint operator/(const mint&val){return mint(*this)/=val;}
    mint pow(int n)const{
        mint res(1),x(*this);
        while(n){
            if(n&1)res*=x;
            x*=x;
            n>>=1;
        }
        return res;
    }
    mint inv()const{return pow(mod-2);}
    //拡張ユークリッドの互除法
    /* mint inv()const{
        int x,y;
        int g=extgcd(v,mod,x,y);
        assert(g==1);
        if(x<0)x+=mod;
        return mint(x);
    }*/
    friend ostream& operator<<(ostream&os,const mint&val){
        return os<<val.v;
    }//出力
    bool operator<(const mint&val)const{return v<val.v;}
    bool operator==(const mint&val)const{return v==val.v;}
    bool operator>(const mint&val)const{return v>val.v;}
};
const ll MAX = 2000010;//設定
mint fac[MAX], finv[MAX], inv[MAX];
// テーブルを作る前処理
void init(){
    fac[0] = fac[1] = 1;
    for(int i=1;i<MAX;i++)fac[i]=fac[i-1]*i;
    finv[MAX-1]=fac[MAX-1].inv();
    for(int i=MAX-2;i>=0;i--)finv[i]=finv[i+1]*(i+1);
    for(int i=MAX-2;i>=1;i--)inv[i]=finv[i]+fac[i-1];
}
//階乗
mint factor(ll n,ll k){
  if (n<k) return 0;
  if (n<0 || k<0) return 0;
  return fac[n]*finv[k];
}
// 二項係数計算
mint COM(int n, int k){
    if (n < k) return 0;
    if (n < 0 || k < 0) return 0;
    return fac[n] * finv[k] * finv[n - k];
}
ll modpow(ll a, ll n) {//a^n(MOD)を求める
    ll res = 1;
    while (n > 0) {
        if (n & 1) res = res * a % mod;
        a = a * a % mod;//次の準備
        n >>= 1;
    }
    return res;
}
ll waru(ll a,ll b){
    return a*modpow(b,mod-2)%mod;
}

ll permutation(ll n,ll r)
{
    ll a=1;
    for(ll i=n-r+1;i<=n;i++)
        a*=i;
    return a;
}

ll nCr(ll n, ll r) {
    ll ans = 1;
    for (ll i = n; i > n - r; --i) {
        ans = ans*i;
    }
    for (ll i = 1 ; i < r + 1; ++i) {
        ans = ans / i;
    }
    return ans;
}

int num = 1;
vector<Pll> A;  // first: 値, second: 遅延評価値
vector<bool> lazyFlag;  // 遅延ありかどうか
const long long INF = 1LL << 60;

// ノード番号 k を遅延評価する (A.at(k).first を正しい値に)
void eval(int k, int l, int r) {
  if (lazyFlag.at(k)) {
    A.at(k).first = A.at(k).second;
    if (r - l > 1) {
      A.at(2*k+1).second = A.at(2*k+2).second = A.at(k).second / 2;
      lazyFlag.at(2*k+1) = lazyFlag.at(2*k+2) = lazyFlag.at(k);
    }
    lazyFlag.at(k) = false;
  }
}

// [a, b) の要素を x に更新
// ノード番号 k は [l, r) に対応している
void update(int a, int b, int x, int k, int l, int r) {
  eval(k, l, r);
  // [a, b) と [l, r) が交差していない
  if (r <= a || b <= l) return;
  // [a, b) が [l, r) を完全に含む
  if (a <= l && r <= b) {
    A.at(k).second = x * (r - l);
    lazyFlag.at(k) = true;
    eval(k, l, r);
  }
  else {
    update(a, b, x, 2*k+1, l, (l+r)/2);
    update(a, b, x, 2*k+2, (l+r)/2, r);
    A.at(k).first = A.at(2*k+1).first + A.at(2*k+2).first;
  }
}
/*
void update(int a, int b, T x) {
    update(a, b, x, 0, 0, n);
}*/
// [a, b) の合計値を返す
long long getSum(int a, int b, int k, int l, int r) {
  eval(k, l, r);
  if (r <= a || b <= l) return 0;
  if (a <= l && r <= b) return A.at(k).first;
  else {
    long long c1 = getSum(a, b, 2*k+1, l, (l+r)/2);
    long long c2 = getSum(a, b, 2*k+2, (l+r)/2, r);
    return c1 + c2;
  }/*
  T getSum(int a, int b) {
        return getSum(a, b, 0, 0, n);
    }*/
}

bool color[100010];
//----------------------------------------------------------------------
int main(int argc, char * argv[]){
    cin.tie(0);
    ios::sync_with_stdio(false);
    //-------------------------------  
    //ll begin_t=clock();
    //freopen("big.txt", "r", stdin);
    //freopen("out3.txt", "w", stdout);
    //------------------------------
    ll n;cin>>n;
    V<ll>m(n);
    V<V<ll>>M(n);
    V<ll>all;
    for(ll i=0;i<n;i++){
        cin>>m[i];
        for(ll j=0;j<m[i];j++){
            ll t;cin>>t;
            M[i].pb(t);
            all.pb(t);
        }
        sort(all(M[i]));
        reverse(all(M[i]));
    }
    sort(all(all));
    map<ll,ll>MA;
    ll cnt=0;
    MA[all[0]]=cnt++;
    for(ll i=1;i<all.size();i++){
        if(all[i]!=all[i-1]){
            MA[all[i]]=cnt++;
        }
    }
    for(ll i=0;i<n;i++){
        for(ll j=0;j<m[i];j++){
            M[i][j]=MA[M[i][j]];
        }
    }
    mint ans=1;
    num = 1;
    while (num < 200010) num *= 2;  // 要素数は 2 のべき乗にする
    // 要素数 n のときに必要なノード数は 2*n - 1
    A = vector<Pll>(2*num - 1, make_pair(0, 0));
    lazyFlag = vector<bool>(2*num - 1, false);

    //update(0,num,1,0,0,num);

    for(ll i=0;i<n;i++){
        for(ll j=0;j<m[i];j++){
            //update(M[i][j],M[i][j]+1,1,0,0,num);
            ans+=1;
            //cout<<M[i][j]<<" ";
            ll tmp =getSum(0,M[i][j],0,0,num);
            //cout<<tmp<<endl;
            ans+=tmp;
            if(tmp+1>getSum(M[i][j],M[i][j]+1,0,0,num))
                update(M[i][j],M[i][j]+1,tmp+1,0,0,num);
        }
        if(i==0){
         //   cout<<getSum(0,3,0,0,num)<<endl;
        }
    }

    cout<<ans<<endl;
    //------------------------------
    //fclose(stdin);
    //fclose(stdout);
    //ll end_t=clock();cout<<"time="<<end_t-begin_t<<"ms"<<endl;
    //------------------------------- 
    return 0;
}
//----------------------------------------------------------------------
accuracy: 0.3181818181818182
time_ms: 130
memory_kb: 68060
final_rank: 17