#include <bits/stdc++.h>
using namespace std;
template <typename T>
vector<T> compress(vector<T> A) {
  sort(A.begin(), A.end());
  A.erase(unique(A.begin(), A.end()), A.end());
  return A;
}
template <typename T>
struct BIT {
  int n;
  vector<T> dat;
  BIT(int n = 0) { initialize(n); }
  void initialize(int nin) {
    n = nin;
    dat.resize(n, 0);
  }
  T sum(int i) {
    T s = 0;
    while (i >= 0) {
      s += dat[i];
      i = (i & (i + 1)) - 1;
    }
    return s;
  }
  T sum_between(int i, int j) { return sum(j) - sum(i - 1); }
  void plus(int i, T x) {
    while (i < n) {
      dat[i] += x;
      i |= i + 1;
    }
  }
  int lower_bound(T x) {
    if (x <= 0) return -1;
    int ret = -1;
    int k = 1;
    while (2 * k <= n) k <<= 1;
    for (; k > 0; k >>= 1) {
      if (ret + k < n && dat[ret + k] < x) {
        x -= dat[ret + k];
        ret += k;
      }
    }
    return ret + 1;
  }
};
struct UnionFind {
  vector<int> par;
  vector<int> sz;
  UnionFind(int n = 0) {
    if (n > 0) initialize(n);
  }
  void initialize(int n) {
    par.resize(n);
    sz.assign(n, 1);
    for (int i = 0; i < n; i++) {
      par[i] = i;
    }
  }
  int find(int x) {
    if (par[x] == x) {
      return x;
    } else {
      return par[x] = find(par[x]);
    }
  }
  bool unite(int x, int y) {
    x = find(x), y = find(y);
    if (x == y) return false;
    if (sz[x] > sz[y]) swap(x, y);
    par[x] = y;
    sz[y] += sz[x];
    return true;
  }
  bool same(int x, int y) { return find(x) == find(y); }
  int size(int x) { return sz[find(x)]; }
};
int main() {
  int N, K;
  cin >> N >> K;
  vector<vector<int>> S(N, vector<int>(K));
  vector<int> ss;
  for (int i = 0; i < N; i++)
    for (int k = 0; k < K; k++) {
      scanf("%d", &S[i][k]);
      ss.push_back(S[i][k]);
    }
  ss = compress(ss);
  for (int i = 0; i < N; i++)
    for (int& a : S[i]) a = lower_bound(ss.begin(), ss.end(), a) - ss.begin();
  int sz = ss.size();
  map<int, int> s2i;
  for (int i = 0; i < N; i++) s2i[S[i][0]] = i;
  UnionFind uf(N);
  BIT<int> bit_min[10], bit_max[10];
  for (int k = 0; k < K; k++) {
    bit_min[k].initialize(sz);
    bit_max[k].initialize(sz);
  }
  auto get_max = [&](int k, int G) { return bit_max[k].lower_bound(G); };
  auto get_min = [&](int k, int G) { return bit_min[k].lower_bound(G); };
  auto merge_between = [&](int a, int b) {
    vector<int> ids;
    for (int i = a; i <= b; i++) {
      int idx = s2i[get_min(0, i)];
      ids.push_back(idx);
    }
    for (int i : ids) uf.unite(i, ids[0]);
    for (int k = 0; k < K; k++) {
      for (int i = b; i >= a + 1; i--) bit_min[k].plus(get_min(k, i), -1);
      for (int i = b - 1; i >= a; i--) bit_max[k].plus(get_max(k, i), -1);
    }
  };
  auto add_group = [&](int G, int idx) {
    int gidx = s2i[get_min(0, G)];
    uf.unite(gidx, idx);
    for (int k = 0; k < K; k++) {
      int mn = get_min(k, G);
      int mx = get_max(k, G);
      if (S[idx][k] < mn) {
        bit_min[k].plus(mn, -1);
        bit_min[k].plus(S[idx][k], 1);
      }
      if (mx < S[idx][k]) {
        bit_max[k].plus(mx, -1);
        bit_max[k].plus(S[idx][k], 1);
      }
    }
  };
  auto make_single_group = [&](int idx) {
    for (int k = 0; k < K; k++) {
      bit_min[k].plus(S[idx][k], 1);
      bit_max[k].plus(S[idx][k], 1);
    }
  };
  for (int i = 0; i < N; i++) {
    vector<int> rg, lg;
    bool incl = false;
    for (int k = 0; k < K; k++) {
      int G = bit_min[k].sum(S[i][k]);
      rg.push_back(G);
      if (bit_max[k].lower_bound(G) > S[i][k]) {
        incl = true;
      } else {
        G++;
      }
      lg.push_back(G);
    }
    int mn = *min_element(lg.begin(), lg.end());
    int mx = *max_element(rg.begin(), rg.end());
    if (mn <= mx) {
      if (mn < mx) merge_between(mn, mx);
      add_group(mn, i);
    } else if (incl) {
      add_group(mn, i);
    } else {
      make_single_group(i);
    }
    int maxG = bit_min[0].sum(sz - 1);
    int idx = s2i[get_min(0, maxG)];
    int ans = uf.size(idx);
    printf("%d\n", ans);
  }
  return 0;
}
