#include <bits/stdc++.h>
using std ::lower_bound;
using std ::priority_queue;
using std ::sort;
using std ::unique;
using std ::vector;
template <typename T>
T max(T x, T y) {
  return (x > y) ? x : y;
}
template <typename T>
T min(T x, T y) {
  return (x < y) ? x : y;
}
template <typename T>
bool chkmax(T &x, T y) {
  return (x >= y) ? 0 : (x = y, 1);
}
template <typename T>
bool chkmin(T &x, T y) {
  return (x <= y) ? 0 : (x = y, 1);
}
template <typename T>
T read(T &in) {
  in = 0;
  char ch;
  T f = 1;
  while (!isdigit(ch = getchar()))
    if (ch == '-') f = -1;
  while (isdigit(ch)) in = in * 10 + ch - '0', ch = getchar();
  return in *= f;
}
static const int max1 = 100000 + 11;
static const int max2 = 200000 + 11;
static const int max3 = 800000 + 11;
int n;
int X1[max1], Y1[max1], X2[max1], Y2[max1];
int dx[max2], dy[max2];
bool D[max1], see[max1];
vector<int> L[max2];
priority_queue<int> H[max3];
int MAX[max3], MIN[max3];
int Get(int o) {
  priority_queue<int> &q = H[o];
  while (!q.empty() && D[q.top()]) q.pop();
  return q.empty() ? -1 : q.top();
}
void update(int o) {
  MAX[o] = max(MAX[o << 1], MAX[o << 1 | 1]);
  MIN[o] = min(MIN[o << 1], MIN[o << 1 | 1]);
  int t = Get(o);
  if (t > MAX[o]) {
    if (see[t] || t < MIN[o])
      MAX[o] = -1;
    else
      MAX[o] = t;
  }
  chkmax(MIN[o], t);
}
void MDY(int L, int R, int x, int o = 1, int l = 1, int r = dy[0]) {
  if (L <= l && r <= R) {
    if (x > 0) H[o].push(x);
    if (l == r) {
      MAX[o] = MIN[o] = Get(o);
      if (MAX[o] > 0 && see[MAX[o]]) MAX[o] = -1;
    } else
      update(o);
    return;
  }
  int mid = (l + r) >> 1;
  if (mid >= L) MDY(L, R, x, o << 1, l, mid);
  if (mid < R) MDY(L, R, x, o << 1 | 1, mid + 1, r);
  update(o);
}
int main() {
  read(n);
  for (int i = (1), ir = (n); i <= (ir); ++i)
    read(X1[i]), read(Y1[i]), read(X2[i]), read(Y2[i]);
  for (int i = (1), ir = (n); i <= (ir); ++i) {
    dx[++dx[0]] = X1[i], dx[++dx[0]] = X2[i];
    dy[++dy[0]] = Y1[i], dy[++dy[0]] = Y2[i];
  }
  sort(1 + dx, 1 + dx[0] + dx), sort(1 + dy, 1 + dy[0] + dy);
  dx[0] = unique(1 + dx, 1 + dx[0] + dx) - dx - 1,
  dy[0] = unique(1 + dy, 1 + dy[0] + dy) - dy - 1;
  for (int i = (1), ir = (n); i <= (ir); ++i) {
    X1[i] = lower_bound(1 + dx, 1 + dx[0] + dx, X1[i]) - dx + 1;
    X2[i] = lower_bound(1 + dx, 1 + dx[0] + dx, X2[i]) - dx;
    Y1[i] = lower_bound(1 + dy, 1 + dy[0] + dy, Y1[i]) - dy + 1;
    Y2[i] = lower_bound(1 + dy, 1 + dy[0] + dy, Y2[i]) - dy;
    L[X1[i]].push_back(i), L[X2[i] + 1].push_back(-i);
  }
  ++dx[0], ++dy[0];
  int Ans = 1;
  memset(MAX, -1, sizeof MAX), memset(MIN, -1, sizeof MIN);
  for (int i = (1), ir = (dx[0]); i <= (ir); ++i) {
    for (vector<int>::iterator j = L[i].begin(); j != L[i].end(); ++j) {
      if (*j < 0) D[-*j] = 1;
      MDY(Y1[abs(*j)], Y2[abs(*j)], *j);
    }
    while (MAX[1] > 0) {
      see[MAX[1]] = 1, ++Ans;
      MDY(Y1[MAX[1]], Y2[MAX[1]], 0);
    }
  }
  printf("%d\n", Ans);
  return 0;
}
