Arkady has got an infinite plane painted in color 0. Then he draws n rectangles filled with paint with sides parallel to the Cartesian coordinate axes, one after another. The color of the i-th rectangle is i (rectangles are enumerated from 1 to n in the order he draws them). It is possible that new rectangles cover some of the previous ones completely or partially.

Count the number of different colors on the plane after Arkady draws all the rectangles.

Input

The first line contains a single integer n (1 ≤ n ≤ 100 000) — the number of rectangles.

The i-th of the next n lines contains 4 integers x_1, y_1, x_2 and y_2 (-10^9 ≤ x_1 < x_2 ≤ 10^9, -10^9 ≤ y_1 < y_2 ≤ 10^9) — the coordinates of corners of the i-th rectangle.

Output

In the single line print the number of different colors in the plane, including color 0.

Examples

Input

5
-1 -1 1 1
-4 0 0 4
0 0 4 4
-4 -4 0 0
0 -4 4 0


Output

5

Input

4
0 0 4 4
-4 -4 0 0
0 -4 4 0
-2 -4 2 4


Output

5

Note

<image> That's how the plane looks in the first sample

<image> That's how the plane looks in the second sample

0 = white, 1 = cyan, 2 = blue, 3 = purple, 4 = yellow, 5 = red. 
#include <bits/stdc++.h>
using namespace std;
const int Imx = 2147483647;
const long long Lbig = 2e18;
const int mod = 1e9 + 7;
struct fastio {
  char s[100000];
  int it, len;
  fastio() { it = len = 0; }
  inline char get() {
    if (it < len) return s[it++];
    it = 0;
    len = fread(s, 1, 100000, stdin);
    if (len == 0)
      return EOF;
    else
      return s[it++];
  }
  bool notend() {
    char c = get();
    while (c == ' ' || c == '\n') c = get();
    if (it > 0) it--;
    return c != EOF;
  }
} _buff;
inline long long getnum() {
  long long r = 0;
  bool ng = 0;
  char c;
  c = _buff.get();
  while (c != '-' && (c < '0' || c > '9')) c = _buff.get();
  if (c == '-') ng = 1, c = _buff.get();
  while (c >= '0' && c <= '9') r = r * 10 + c - '0', c = _buff.get();
  return ng ? -r : r;
}
template <class T>
inline void putnum(T x) {
  if (x < 0) putchar('-'), x = -x;
  register short a[20] = {}, sz = 0;
  while (x) a[sz++] = x % 10, x /= 10;
  if (sz == 0) putchar('0');
  for (int i = sz - 1; i >= 0; i--) putchar('0' + a[i]);
}
inline char getreal() {
  char c = _buff.get();
  while (c <= 32) c = _buff.get();
  return c;
}
long long qpow(long long x, long long k) {
  return k == 0 ? 1
                : 1ll * qpow(1ll * x * x % mod, k >> 1) * (k & 1 ? x : 1) % mod;
}
int n;
vector<int> vy;
int getidy(int y) { return upper_bound(vy.begin(), vy.end(), y) - vy.begin(); }
bool ANS[100111];
struct node {
  set<int> st, tst;
  int mn, mx;
  int cmxu, hmxu;
  void add(int x) {
    st.insert(x);
    tst.insert(x);
    mx = *st.rbegin();
  }
  void del(int x) {
    st.erase(x);
    tst.erase(x);
    assert(st.size() > 0);
    mx = *st.rbegin();
  }
  node() {
    add(0);
    cmxu = hmxu = mn = 0;
  }
  void query(int x) {
    while (tst.size() > 0 && *tst.rbegin() >= x)
      ANS[*tst.rbegin()] = 1, tst.erase(--tst.end());
  }
} a[800111];
void updateu(int p) { a[p].cmxu = max(a[p >> 1].cmxu, a[p].mx); }
void update(int p, bool isl) {
  a[p].mn = max(a[p].mx, (isl ? 0 : min(a[p << 1].mn, a[p << 1 | 1].mn)));
}
void deltag(int p, bool isl) {
  a[p].query(max(a[p].mn, max(a[p].hmxu, a[p].mx)));
  if (!isl) {
    int cmxu = max(a[p].hmxu, a[p].mx);
    a[p << 1].hmxu = min(a[p << 1].hmxu, cmxu),
           a[p << 1 | 1].hmxu = min(a[p << 1 | 1].hmxu, cmxu);
  }
  a[p].hmxu = a[p >> 1].cmxu;
}
void modify(int x, int y, int op, int v, int l, int r, int p = 1) {
  deltag(p, l == r);
  updateu(p);
  if (x <= l && r <= y) {
    if (op == 1)
      a[p].add(v);
    else
      a[p].del(v);
    updateu(p);
    update(p, l == r);
    if (l < r) {
      a[p << 1].hmxu = min(a[p << 1].hmxu, a[p].cmxu);
      a[p << 1 | 1].hmxu = min(a[p << 1 | 1].hmxu, a[p].cmxu);
    }
    a[p].query(max(a[p].mn, a[p].cmxu));
    return;
  }
  int m = l + r >> 1;
  if (x <= m) modify(x, y, op, v, l, m, p << 1);
  if (m < y) modify(x, y, op, v, m + 1, r, p << 1 | 1);
  update(p, l == r);
  a[p].query(max(a[p].mn, a[p].cmxu));
}
void pushdownall(int l, int r, int p) {
  deltag(p, l == r);
  updateu(p);
  a[p].query(max(a[p].mn, a[p].cmxu));
  if (l == r) return;
  int m = l + r >> 1;
  pushdownall(l, m, p << 1);
  pushdownall(m + 1, r, p << 1 | 1);
}
struct query {
  int op, x, yl, yr, id;
  bool operator<(const query &t) const {
    return make_pair(make_pair(x, op), op == 1 ? -id : id) <
           make_pair(make_pair(t.x, t.op), t.op == 1 ? -t.id : t.id);
  }
};
vector<query> qr;
int main() {
  n = getnum();
  for (int i = 1; i <= n; i++) {
    int xl, yl, xr, yr;
    xl = getnum(), yl = getnum();
    xr = getnum(), yr = getnum();
    yr--;
    vy.push_back(yl);
    vy.push_back(yr + 1);
    query tmp;
    tmp.yl = yl;
    tmp.yr = yr;
    tmp.id = i;
    tmp.x = xl;
    tmp.op = 1;
    qr.push_back(tmp);
    tmp.x = xr;
    tmp.op = 2;
    qr.push_back(tmp);
  }
  sort(vy.begin(), vy.end());
  vy.erase(unique(vy.begin(), vy.end()), vy.end());
  sort(qr.begin(), qr.end());
  int sz = vy.size();
  for (int i = 0; i < qr.size(); i++) {
    int yl = getidy(qr[i].yl);
    int yr = getidy(qr[i].yr);
    modify(yl, yr, qr[i].op, qr[i].id, 1, sz);
  }
  int ans = 0;
  for (int i = 0; i <= n; i++) ans += ANS[i];
  cout << ans << endl;
  return 0;
}
