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;
namespace Elaina {
template <class T>
inline T Max(const T x, const T y) {
  return x < y ? y : x;
}
template <class T>
inline T Min(const T x, const T y) {
  return x < y ? x : y;
}
template <class T>
inline T fab(const T x) {
  return x < 0 ? -x : x;
}
template <class T>
inline void getMax(T& x, const T y) {
  x = Max(x, y);
}
template <class T>
inline void getMin(T& x, const T y) {
  x = Min(x, y);
}
template <class T>
T gcd(const T x, const T y) {
  return y ? gcd(y, x % y) : x;
}
template <class T>
inline T readin(T x) {
  x = 0;
  int f = 0;
  char c;
  while ((c = getchar()) < '0' || '9' < c)
    if (c == '-') f = 1;
  for (x = (c ^ 48); '0' <= (c = getchar()) && c <= '9';
       x = (x << 1) + (x << 3) + (c ^ 48))
    ;
  return f ? -x : x;
}
template <class T>
void fwrit(const T x) {
  if (x < 0) return putchar('-'), fwrit(-x);
  if (x > 9) fwrit(x / 10);
  putchar(x % 10 ^ 48);
}
}  // namespace Elaina
using namespace Elaina;
const int maxn = 1e5;
int yl[maxn + 5], yr[maxn + 5];
struct node {
  int x, l, r, id, opt;
  node() {}
  node(const int X, const int L, const int R, const int I, const int O)
      : x(X), l(L), r(R), id(I), opt(O) {}
  inline int operator<(const node rhs) const { return x < rhs.x; }
} q[maxn * 2 + 5];
int n, cnt;
int y[maxn * 6 + 5], cnty;
int vis[maxn + 5];
namespace segment_tree {
set<int> s[maxn * 24 + 5];
int maxx[maxn * 24 + 5];
int minn[maxn * 24 + 5];
void build(const int i, const int l, const int r) {
  s[i].insert(0);
  minn[i] = maxx[i] = 0;
  if (l == r) return;
  build((i << 1), l, ((l + r) >> 1)),
      build((i << 1 | 1), ((l + r) >> 1) + 1, r);
}
void upload(const int i, const int l, const int r) {
  int mxc = *s[i].rbegin();
  if (l == r)
    maxx[i] = minn[i] = mxc;
  else {
    maxx[i] = max(mxc, max(maxx[(i << 1)], maxx[(i << 1 | 1)]));
    minn[i] = max(mxc, min(minn[(i << 1)], minn[(i << 1 | 1)]));
  }
  if (vis[maxx[i]] || maxx[i] < minn[i]) maxx[i] = 0;
}
void modify(const int c, const int L, const int R, const int type, const int i,
            const int l, const int r) {
  if (L <= l && r <= R) {
    if (type)
      s[i].insert(c);
    else
      s[i].erase(c);
    return upload(i, l, r);
  }
  if (L <= ((l + r) >> 1)) modify(c, L, R, type, (i << 1), l, ((l + r) >> 1));
  if (((l + r) >> 1) < R)
    modify(c, L, R, type, (i << 1 | 1), ((l + r) >> 1) + 1, r);
  upload(i, l, r);
}
void update(const int L, const int R, const int i, const int l, const int r) {
  if (L <= l && r <= R) return upload(i, l, r);
  if (L <= ((l + r) >> 1)) update(L, R, (i << 1), l, ((l + r) >> 1));
  if (((l + r) >> 1) < R) update(L, R, (i << 1 | 1), ((l + r) >> 1) + 1, r);
  upload(i, l, r);
}
}  // namespace segment_tree
inline void input() {
  n = readin(1);
  int x1, x2;
  for (int i = 1; i <= n; ++i) {
    x1 = readin(1), yl[i] = readin(1);
    x2 = readin(1) - 1, yr[i] = readin(1) - 1;
    q[++cnt] = node(x1, yl[i], yr[i], i, 1);
    q[++cnt] = node(x2 + 1, yl[i], yr[i], i, 0);
    y[++cnty] = yl[i] - 1, y[++cnty] = yl[i], y[++cnty] = yl[i] + 1;
    y[++cnty] = yr[i] - 1, y[++cnty] = yr[i], y[++cnty] = yr[i] + 1;
  }
}
inline void hashy() {
  sort(y + 1, y + cnty + 1);
  cnty = unique(y + 1, y + cnty + 1) - y - 1;
  for (int i = 1; i <= cnt; ++i) {
    q[i].l = lower_bound(y + 1, y + cnty + 1, q[i].l) - y;
    q[i].r = lower_bound(y + 1, y + cnty + 1, q[i].r) - y;
  }
  for (int i = 1; i <= n; ++i) {
    yl[i] = lower_bound(y + 1, y + cnty + 1, yl[i]) - y;
    yr[i] = lower_bound(y + 1, y + cnty + 1, yr[i]) - y;
  }
}
inline void scan_line() {
  sort(q + 1, q + cnt + 1);
  segment_tree::build(1, 1, cnty);
  int ans = 0;
  for (int i = 1; i <= cnt; ++i) {
    int j = i;
    while (q[j].x == q[i].x) {
      segment_tree::modify(q[j].id, q[j].l, q[j].r, q[j].opt, 1, 1, cnty);
      ++j;
    }
    i = j - 1;
    while (segment_tree::maxx[1]) {
      int c = segment_tree::maxx[1];
      ++ans, vis[c] = 1;
      segment_tree::update(yl[c], yr[c], 1, 1, cnty);
    }
  }
  printf("%d\n", ans + 1);
}
signed main() {
  input();
  hashy();
  scan_line();
  return 0;
}
