#include <bits/stdc++.h>
#pragma warning(disable : 4996)
template <typename T>
T min(T x, T y) {
  return x < y ? x : y;
}
template <typename T>
T max(T x, T y) {
  return x > y ? x : y;
};
const int MAXN = 300005;
const int INF = 2000000005;
struct pos {
  int x;
  int y;
  pos(int X = 0, int Y = 0) {
    x = X;
    y = Y;
  }
};
bool cmp1(pos a, pos b) {
  if (a.x == b.x) return a.y <= b.y;
  return a.x < b.x;
}
bool cmp2(pos a, pos b) {
  if (a.y == b.y) return a.x <= b.x;
  return a.y < b.y;
}
struct tree {
  pos w;
  int size;
  tree *lson;
  tree *rson;
  tree(pos data = pos()) {
    w = data;
    size = 1;
    lson = rson = NULL;
  }
  void fixup() { size = (lson ? lson->size : 0) + (rson ? rson->size : 0) + 1; }
};
struct pair {
  tree *fir;
  tree *sec;
  pair(tree *F = NULL, tree *S = NULL) {
    fir = F;
    sec = S;
  }
};
bool shouldleft(int a, int b) {
  return (rand() * 10000 + rand()) % (a + b) < a;
}
tree *merge(tree *T1, tree *T2) {
  if (!T1) return T2;
  if (!T2) return T1;
  if (shouldleft(T1->size, T2->size)) {
    T1->rson = merge(T1->rson, T2);
    T1->fixup();
    return T1;
  }
  T2->lson = merge(T1, T2->lson);
  T2->fixup();
  return T2;
}
pair split(tree *T, int k) {
  if (!T) return pair();
  int r = (T->lson ? T->lson->size : 0) + 1;
  if (r <= k) {
    pair t = split(T->rson, k - r);
    T->rson = t.fir;
    T->fixup();
    return pair(T, t.sec);
  }
  pair t = split(T->lson, k);
  T->lson = t.sec;
  T->fixup();
  return pair(t.fir, T);
}
int LorE(tree *T, pos p, bool (*cmp)(pos, pos)) {
  if (!T) return 0;
  return cmp(T->w, p)
             ? (T->lson ? T->lson->size : 0) + 1 + LorE(T->rson, p, cmp)
             : LorE(T->lson, p, cmp);
}
tree *insert(tree *T, pos p, bool (*cmp)(pos, pos)) {
  pair t = split(T, LorE(T, p, cmp));
  return merge(t.fir, merge(new tree(p), t.sec));
}
tree *del(tree *T, pos p, bool (*cmp)(pos, pos)) {
  int n = LorE(T, p, cmp);
  pair t = split(T, n);
  pair t2 = split(t.fir, n - 1);
  return merge(t2.fir, t.sec);
}
tree *get(tree *T, int k) {
  int r = (T->lson ? T->lson->size : 0) + 1;
  if (r == k) return T;
  if (k < r) return get(T->lson, k);
  return get(T->rson, k - r);
}
int solve(tree *T1, tree *T2) {
  int n = T1->size;
  for (int i = 1; i <= n - 1; i++) {
    if (get(T1, i + 1)->w.x > get(T1, i)->w.x + 1) {
      pair t1 = split(T1, i), t2;
      for (int j = 1; j <= i; j++) {
        pos p = get(t1.fir, j)->w;
        t2.fir = insert(t2.fir, p, cmp2);
        T2 = del(T2, p, cmp2);
      }
      t2.sec = T2;
      return solve(t1.fir, t2.fir) + solve(t1.sec, t2.sec);
    }
    if (get(T2, i + 1)->w.y > get(T2, i)->w.y + 1) {
      pair t1, t2 = split(T2, i);
      for (int j = 1; j <= i; j++) {
        pos p = get(t2.fir, j)->w;
        t1.fir = insert(t1.fir, p, cmp1);
        T1 = del(T1, p, cmp1);
      }
      t1.sec = T1;
      return solve(t1.fir, t2.fir) + solve(t1.sec, t2.sec);
    }
    if (get(T1, n - i + 1)->w.x > get(T1, n - i)->w.x + 1) {
      pair t1 = split(T1, n - i), t2;
      for (int j = 1; j <= i; j++) {
        pos p = get(t1.sec, j)->w;
        t2.sec = insert(t2.sec, p, cmp2);
        T2 = del(T2, p, cmp2);
      }
      t2.fir = T2;
      return solve(t1.fir, t2.fir) + solve(t1.sec, t2.sec);
    }
    if (get(T2, n - i + 1)->w.y > get(T2, n - i)->w.y + 1) {
      pair t1, t2 = split(T2, n - i);
      for (int j = 1; j <= i; j++) {
        pos p = get(t2.sec, j)->w;
        t1.sec = insert(t1.sec, p, cmp1);
        T1 = del(T1, p, cmp1);
      }
      t1.fir = T1;
      return solve(t1.fir, t2.fir) + solve(t1.sec, t2.sec);
    }
  }
  return 1;
}
int N;
tree *T1, *T2;
int main() {
  pos p;
  scanf("%d", &N);
  for (int i = 1; i <= N; i++) {
    scanf("%d %d", &p.x, &p.y);
    T1 = insert(T1, p, cmp1);
    T2 = insert(T2, p, cmp2);
  }
  int ans = solve(T1, T2);
  printf("%d", ans);
  return 0;
}
