#include <bits/stdc++.h>
using namespace std;
int read() {
  char c = getchar();
  int d = 0, f = 1;
  for (; c < '0' || c > '9'; c = getchar())
    if (c == '-') f = -1;
  for (; c >= '0' && c <= '9'; d = d * 10 + c - 48, c = getchar())
    ;
  return d * f;
}
const int N = 310000;
const int inf = 1e9;
int n, w, h, sx1[N], sx2[N], sy1[N], sy2[N];
struct dot {
  int x, y, id;
} p[N], q[N * 2];
bool cmpx(dot a, dot b) { return a.x < b.x; }
bool cmpy(dot a, dot b) { return a.y < b.y; }
bool cmpid(dot a, dot b) { return a.id < b.id; }
template <int S>
struct stree {
  int init(int tp) {
    if (tp == 1) return inf;
    if (tp == 2) return -inf;
    if (tp == 3) return 0;
    if (tp == 4) return 0;
  }
  void upd(int tp, int& a, int b) {
    if (tp == 1) {
      if (b < a) a = b;
    } else if (tp == 2) {
      if (b > a) a = b;
    } else if (tp == 3) {
      if (q[b].x < q[a].x) a = b;
    } else if (tp == 4) {
      if (q[b].y < q[a].y) a = b;
    }
  }
  int rx, ry;
  int type, tot, rt[S * 2], ti, mk[S * 2];
  struct node {
    int ch[2], w;
  } a[S * 20];
  void Settype(int tp, int x, int y) {
    type = tp;
    rx = x;
    ry = y;
  }
  void build(int& t, int x, int y) {
    if (!t) {
      t = ++tot;
      a[t].w = init(type);
    }
    if (x == y) return;
    int m = (x + y) >> 1;
    build(a[t].ch[0], x, m);
    build(a[t].ch[1], m + 1, y);
  }
  void Build() { build(rt[ti = 0], rx, ry); }
  void modify(int t, int x, int y, int p, int w) {
    upd(type, a[t].w, w);
    if (x == y) return;
    int m = (x + y) >> 1;
    if (p <= m)
      modify(a[t].ch[0], x, m, p, w);
    else
      modify(a[t].ch[1], m + 1, y, p, w);
  }
  void Modify(int p, int w) { modify(rt[ti], rx, ry, p, w); }
  void insert(int t1, int& t2, int x, int y, int p, int w) {
    a[t2 = ++tot] = a[t1];
    upd(type, a[t2].w, w);
    if (x == y) return;
    int m = (x + y) >> 1;
    if (p <= m)
      insert(a[t1].ch[0], a[t2].ch[0], x, m, p, w);
    else
      insert(a[t1].ch[1], a[t2].ch[1], m + 1, y, p, w);
  }
  void Insert(int p, int w) {
    ++ti;
    insert(rt[ti - 1], rt[ti], rx, ry, p, w);
  }
  void Settime(int t) { mk[t] = rt[ti]; }
  int query(int t, int x, int y, int l, int r) {
    int res = init(type);
    if (!t) return res;
    if (l <= x && y <= r) return a[t].w;
    int m = (x + y) >> 1;
    if (l <= m) upd(type, res, query(a[t].ch[0], x, m, l, r));
    if (r > m) upd(type, res, query(a[t].ch[1], m + 1, y, l, r));
    return res;
  }
  int Query(int t, int x, int y) { return query(mk[t], rx, ry, x, y); }
};
stree<120000> tx1, tx2, ty1, ty2;
stree<120001> tmx, tmy;
int px[N], py[N], sx[N], sy[N];
int solve(int x1, int x2, int y1, int y2) {
  if (x1 > x2 || y1 > y2) return 0;
  x1 = tx2.Query(sx2[x1], y1, y2);
  if (x1 > x2) return 0;
  x2 = tx1.Query(sx1[x2], y1, y2);
  if (x1 > x2) return 0;
  y1 = ty2.Query(sy2[y1], x1, x2);
  if (y1 > y2) return 0;
  y2 = ty1.Query(sy1[y2], x1, x2);
  if (y1 > y2) return 0;
  int id;
  if (q[id = tmx.Query(x2 + 1, y1, y2)].x < x1) {
    int ym = q[id].y;
    return solve(x1, x2, y1, ym - 1) + solve(x1, x2, ym + 1, y2);
  }
  if (q[id = tmy.Query(y2 + 1, x1, x2)].y < y1) {
    int xm = q[id].x;
    return solve(x1, xm - 1, y1, y2) + solve(xm + 1, x2, y1, y2);
  }
  return 1;
}
int main() {
  n = read();
  for (int i = 1; i <= n; ++i) p[i].x = read(), p[i].y = read(), p[i].id = i;
  sort(p + 1, p + n + 1, cmpx);
  for (int i = 1, la = 0; i <= n; ++i) {
    if (i == 1 || p[i].x == la + 1)
      w++;
    else if (p[i].x > la + 1)
      w += 2;
    la = p[i].x;
    p[i].x = w;
  }
  sort(p + 1, p + n + 1, cmpy);
  for (int i = 1, la = 0; i <= n; ++i) {
    if (i == 1 || p[i].y == la + 1)
      h++;
    else if (p[i].y > la + 1)
      h += 2;
    la = p[i].y;
    p[i].y = h;
  }
  for (int i = 1; i <= n; ++i) sx1[p[i].x] = sx2[p[i].x] = p[i].x;
  for (int i = 1; i <= n; ++i) sy1[p[i].y] = sy2[p[i].y] = p[i].y;
  for (int i = 1; i <= w; ++i)
    if (!sx1[i]) sx1[i] = sx1[i - 1];
  for (int i = w; i >= 1; --i)
    if (!sx2[i]) sx2[i] = sx2[i + 1];
  for (int i = 1; i <= h; ++i)
    if (!sy1[i]) sy1[i] = sy1[i - 1];
  for (int i = h; i >= 1; --i)
    if (!sy2[i]) sy2[i] = sy2[i + 1];
  sort(p + 1, p + n + 1, cmpid);
  for (int i = 1; i <= n; ++i) q[i] = p[i];
  q[0] = (dot){inf, inf, 0};
  for (int i = 1; i <= w; ++i) q[n + i] = (dot){i, 0, n + i};
  for (int i = 1; i <= h; ++i) q[n + w + i] = (dot){0, i, n + w + i};
  sort(p + 1, p + n + 1, cmpx);
  tx1.Settype(2, 1, h);
  tx1.Build();
  for (int i = 1; i <= n; ++i) tx1.Insert(p[i].y, p[i].x), tx1.Settime(p[i].x);
  tx2.Settype(1, 1, h);
  tx2.Build();
  for (int i = n; i >= 1; --i) tx2.Insert(p[i].y, p[i].x), tx2.Settime(p[i].x);
  sort(p + 1, p + n + 1, cmpy);
  ty1.Settype(2, 1, w);
  ty1.Build();
  for (int i = 1; i <= n; ++i) ty1.Insert(p[i].x, p[i].y), ty1.Settime(p[i].y);
  ty2.Settype(1, 1, w);
  ty2.Build();
  for (int i = n; i >= 1; --i) ty2.Insert(p[i].x, p[i].y), ty2.Settime(p[i].y);
  sort(p + 1, p + n + 1, cmpx);
  for (int i = 1; i <= h; ++i) p[n + i] = (dot){w + 1, i};
  tmx.Settype(3, 1, h);
  tmx.Build();
  for (int i = 1; i <= h; ++i) px[i] = n + w + i;
  for (int i = 1; i <= n + h; ++i) sx[i] = px[p[i].y], px[p[i].y] = p[i].id;
  for (int i = n + h; i > n; --i) tmx.Modify(i - n, sx[i]);
  tmx.Settime(w + 1);
  for (int i = w, cnt = n; i >= 1; --i) {
    while (cnt >= 1 && p[cnt].x >= i) tmx.Insert(p[cnt].y, sx[cnt]), cnt--;
    tmx.Settime(i);
  }
  sort(p + 1, p + n + 1, cmpy);
  for (int i = 1; i <= w; ++i) p[n + i] = (dot){i, h + 1};
  tmy.Settype(4, 1, w);
  tmy.Build();
  for (int i = 1; i <= w; ++i) py[i] = n + i;
  for (int i = 1; i <= n + w; ++i) sy[i] = py[p[i].x], py[p[i].x] = p[i].id;
  for (int i = n + w; i > n; --i) tmy.Modify(i - n, sy[i]);
  tmy.Settime(h + 1);
  for (int i = h, cnt = n; i >= 1; --i) {
    while (cnt >= 1 && p[cnt].y >= i) tmy.Insert(p[cnt].x, sy[cnt]), cnt--;
    tmy.Settime(i);
  }
  printf("%d\n", solve(1, w, 1, h));
}
