#include <bits/stdc++.h>
using namespace std;
const int MX = 5 * 1e4 + 10;
const int MK = 11;
bool can_win(const int* a, const int* b);
namespace Treap {
vector<int> fixed_rand;
void pre() {
  fixed_rand.reserve(MX);
  for (int i = 0; i < MX; i++) fixed_rand.push_back(i);
  random_shuffle(fixed_rand.begin(), fixed_rand.end());
}
struct Node {
  int LSon, RSon;
  int size;
  int sizeOn;
  int minVal[MK];
  int maxVal[MK];
  int pr;
};
Node Tree[MX];
int tt = 0;
int new_node(const int* a) {
  tt++;
  Tree[tt].size = 1;
  Tree[tt].sizeOn = 1;
  memcpy(Tree[tt].minVal, a, sizeof(Tree[tt].minVal));
  memcpy(Tree[tt].maxVal, a, sizeof(Tree[tt].maxVal));
  Tree[tt].pr = fixed_rand[tt];
  return tt;
}
void update(int v) {
  Tree[v].sizeOn = Tree[v].size;
  if (Tree[v].LSon != 0) {
    Tree[v].sizeOn += Tree[Tree[v].LSon].sizeOn;
  }
  if (Tree[v].RSon != 0) {
    Tree[v].sizeOn += Tree[Tree[v].RSon].sizeOn;
  }
}
int merge(int a, int b) {
  if (a == b || b == 0) return (a + b);
  int v;
  if (Tree[a].pr > Tree[b].pr) {
    Tree[a].RSon = merge(Tree[a].RSon, b);
    v = a;
  } else {
    Tree[b].LSon = merge(a, Tree[b].LSon);
    v = b;
  }
  update(v);
  return v;
}
void split_can_win(int v, int& a, int& b, const int* power) {
  a = 0;
  b = 0;
  if (v == 0) return;
  if (can_win(power, Tree[v].minVal)) {
    split_can_win(Tree[v].LSon, a, Tree[v].LSon, power);
    b = v;
  } else {
    split_can_win(Tree[v].RSon, Tree[v].RSon, b, power);
    a = v;
  }
  update(v);
}
void split_can_lose(int v, int& a, int& b, const int* power) {
  a = 0;
  b = 0;
  if (v == 0) return;
  if (can_win(Tree[v].maxVal, power)) {
    split_can_lose(Tree[v].RSon, Tree[v].RSon, b, power);
    a = v;
  } else {
    split_can_lose(Tree[v].LSon, a, Tree[v].LSon, power);
    b = v;
  }
  update(v);
}
int get_first_size(int v) {
  while (Tree[v].LSon != 0) {
    v = Tree[v].LSon;
  }
  return Tree[v].size;
}
void colapse(int v) {
  Tree[v].size = Tree[v].sizeOn;
  int left_v = v;
  while (Tree[left_v].LSon > 0) left_v = Tree[left_v].LSon;
  int right_v = v;
  while (Tree[right_v].RSon > 0) right_v = Tree[right_v].RSon;
  memcpy(Tree[v].maxVal, Tree[left_v].maxVal, sizeof(Tree[v].maxVal));
  memcpy(Tree[v].minVal, Tree[right_v].minVal, sizeof(Tree[v].minVal));
  Tree[v].LSon = Tree[v].RSon = 0;
}
}  // namespace Treap
int power[MX][MK];
int k;
bool can_win(const int* a, const int* b) {
  if (k <= 10) {
    for (int i = 0; i < k; i++) {
      if (a[i] > b[i]) return true;
    }
    return false;
  } else {
    __builtin_unreachable();
  }
}
int main() {
  Treap::pre();
  int n;
  ignore = scanf("%d %d", &n, &k);
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < k; j++) {
      ignore = scanf("%d", &power[i][j]);
    }
  }
  int root = Treap::new_node(power[0]);
  printf("%d\n", Treap::get_first_size(root));
  for (int i = 1; i < n; i++) {
    int left, mid, right;
    Treap::split_can_win(root, left, right, power[i]);
    Treap::split_can_lose(right, mid, right, power[i]);
    if (mid == 0) {
      mid = Treap::new_node(power[i]);
    } else {
      Treap::colapse(mid);
      Treap::Tree[mid].size++;
      Treap::Tree[mid].sizeOn++;
      for (int j = 0; j < MK; j++) {
        Treap::Tree[mid].maxVal[j] =
            max(Treap::Tree[mid].maxVal[j], power[i][j]);
        Treap::Tree[mid].minVal[j] =
            min(Treap::Tree[mid].minVal[j], power[i][j]);
      }
    }
    root = Treap::merge(left, Treap::merge(mid, right));
    printf("%d\n", Treap::get_first_size(root));
  }
  return 0;
}
