#include <bits/stdc++.h>
using namespace std;
struct Edge {
  long long l;
  int e, n;
} e[200010 << 1];
int hd[200010], cur[200010], cnt = 1;
void add(int a, int b, long long l) {
  e[++cnt].e = b;
  e[cnt].l = l;
  e[cnt].n = hd[a];
  hd[a] = cnt;
  e[++cnt].e = a;
  e[cnt].l = 0;
  e[cnt].n = hd[b];
  hd[b] = cnt;
}
long long inf = 1e15;
int n, m, s, t;
long long a[200010];
int dep[200010];
queue<int> Q;
long long dfs(int p, long long flow) {
  if (p == t) return flow;
  int i;
  for (i = cur[p]; i; i = e[i].n) {
    int q = e[i].e;
    cur[p] = i;
    if (dep[q] == dep[p] + 1 && e[i].l) {
      long long ans = dfs(q, min(flow, e[i].l));
      if (ans) {
        e[i].l -= ans;
        e[i ^ 1].l += ans;
        return ans;
      }
    }
  }
  return 0;
}
int bfs() {
  memset(dep, 0, sizeof(dep));
  Q.push(s);
  dep[s] = 1;
  int i;
  while (!Q.empty()) {
    int p = Q.front();
    Q.pop();
    for (i = hd[p]; i; i = e[i].n) {
      int q = e[i].e;
      if (!dep[q] && e[i].l) dep[q] = dep[p] + 1, Q.push(q);
    }
  }
  return dep[t];
}
int tot;
long long dinic() {
  int i;
  long long d, ans = 0;
  while (bfs()) {
    for (i = 0; i <= tot; i++) cur[i] = hd[i];
    while ((d = dfs(s, inf))) ans += d;
  }
  return ans;
}
int id[200010], L[200010], R[200010];
void build(int p, int l, int r) {
  id[p] = ++tot;
  L[p] = l;
  R[p] = r;
  if (l == r) {
    add(tot, l, 1);
    return;
  }
  build(p << 1, l, (l + r) >> 1);
  build(p << 1 | 1, ((l + r) >> 1) + 1, r);
  add(id[p], id[p << 1], inf);
  add(id[p], id[p << 1 | 1], inf);
}
void upd(int p, int l, int r) {
  if (L[p] >= l && R[p] <= r) {
    add(tot, id[p], 1);
    return;
  }
  if (L[p] > r || R[p] < l) return;
  upd(p << 1, l, r);
  upd(p << 1 | 1, l, r);
}
map<int, int> mp[200010];
int vis[200010], start, ret;
void solve(int x) {
  if (x >= start) {
    ret = x - start;
    return;
  }
  map<int, int>::iterator it = mp[x].begin();
  solve(it->first);
  --it->second;
  if (!it->second) mp[x].erase(it);
}
int main() {
  int i, j, u, k, l, r, opt;
  int temp = 0;
  scanf("%d%d", &n, &m);
  tot = m;
  build(1, 1, m);
  s = ++tot;
  t = ++tot;
  start = tot;
  for (i = 1; i <= n; i++) {
    ++tot;
    scanf("%d", &opt);
    if (opt == 0) {
      add(s, tot, 1);
      scanf("%d", &k);
      while (k--) scanf("%d", &u), add(tot, u, 1);
    } else if (opt == 1) {
      add(s, tot, 1);
      scanf("%d%d", &l, &r);
      upd(1, l, r);
    } else {
      int A, B, C;
      scanf("%d%d%d", &A, &B, &C);
      add(tot, A, 1);
      add(tot, B, 0);
      e[cnt].l = 1;
      vis[B] = 1;
      add(tot, C, 1);
      e[cnt].l = 1;
      vis[C] = 1;
      temp += 2;
    }
  }
  for (i = 1; i <= m; i++)
    if (!vis[i]) add(i, t, 1);
  printf("%I64d\n", dinic() + temp);
  for (i = 1; i <= tot; i++)
    for (j = hd[i]; j; j = e[j].n)
      if ((j & 1) && e[j].l) mp[i][e[j].e] = e[j].l;
  for (i = 1; i <= m; i++) {
    int flag = 0;
    for (j = hd[i]; j; j = e[j].n)
      if (e[j].e == t && e[j].l) {
        flag = 1;
        break;
      }
    if (flag) continue;
    solve(i);
    printf("%d %d\n", ret, i);
  }
  return 0;
}
