#include using namespace std; using ll = long long; using ld = long double; #define print(x) cerr << #x << " = " << x << endl #define int long long template ostream& operator<<(ostream &out, vector &cont) { out << "["; for (const auto &x : cont) out << x << ", "; out << "]"; return out; } struct SegTree { int N, neutral = 0; vector tree; SegTree(int n) { N = n; N = 1 << (32 - __builtin_clz(N)); tree.assign(2 * N, 0); } int query(int l, int r, int i, int j, int idx) { // lezi vo vnutri if (l <= i && j <= r) { return tree[idx]; // lezi mimo } else if (j <= l || r <= i) { } else { int mid = (i + j) / 2; int q1 = query(l, r, i, mid, 2 * idx); int q2 = query(l, r, mid, j, 2 * idx + 1); return q1 + q2; } return 0; } void update(int val, int idx) { tree[idx] += val; if (idx != 1) update(val, idx / 2); } }; int32_t main() { /* vector a = { 0, 0, 0, 1, 8, 9, 7 }; SegTree st(a); st.update(3, st.N + 0); st.update(10, st.N + 1); st.update(1, st.N + 2); st.update(1, st.N + 3); st.update(8, st.N + 4); st.update(9, st.N + 5); st.update(7, st.N + 6); print(st.tree); print(st.query(2, 5, 0, st.N, 1)); */ int N; cin >> N; SegTree st(N); vector> g(N); for (int i = 0; i < N; i++) { int K; cin >> K; for (int j = 0; j < K; j++) { int idx; cin >> idx; g[i].push_back(idx); st.update(1, st.N + idx); } } int ans = 0; for (int i = 0; i < N; i++) { for (int j : g[i]) { st.update(-1, st.N + j); } for (int j : g[i]) { ans += st.query(0, j, 0, st.N, 1); } } cout << ans << endl; }