#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 100;
int b[maxn];
struct dsu {
  vector<int> par;
  int n;
  dsu(int n) : n(n), par(n) { iota(par.begin(), par.end(), 0); }
  int find(int v) {
    if (v == par[v]) return v;
    return par[v] = find(par[v]);
  }
  bool merge(int x, int y) {
    x = find(x);
    y = find(y);
    if (x != y) {
      par[x] = y;
      return 1;
    }
    return 0;
  }
};
int main() {
  int t, x = 0;
  cin >> t;
  while (t--) {
    int n;
    cin >> n;
    vector<int> a(n);
    for (int i = 0; i < n; i++) cin >> a[i];
    int ptr = -1;
    for (int v = 0; v < maxn; v++) {
      if (ptr + 1 < n and a[ptr + 1] == v) ++ptr;
      b[v] = ptr;
    }
    vector<vector<int>> w(1, vector<int>(n, -1));
    vector<dsu> d(1, dsu(n + 1));
    vector<bool> vis;
    for (int i = n - 1; i >= 0; i--) {
      int st = 0, j = 0;
      while (st < i) {
        if (j == w.size()) {
          w.emplace_back(n, -1);
          d.emplace_back(n + 1);
        }
        int f = i - 1;
        int temp = w[j][i];
        if (temp != -1) {
          int val = a[i] - (a[temp] - a[i]);
          f = (val <= 0 ? -1 : b[val]);
        }
        if (st <= f) {
          int pos = d[j].find(st);
          while (pos <= f) {
            w[j][pos] = i;
            d[j].merge(pos, pos + 1);
            pos = d[j].find(pos);
          }
          st = f + 1;
        }
        j++;
      }
      int g = 0;
      while (g < w.size() and w[g][i] != -1) g++;
      if (g >= vis.size()) vis.resize(g + 1);
      vis[g] = 1;
    }
    int res = 0;
    while (res < vis.size() and vis[res]) res++;
    x ^= res;
  }
  cout << (x > 0 ? "YES" : "NO");
  return 0;
}
