#include <bits/stdc++.h>
#pragma GCC target("avx2")
#pragma GCC optimization("O3")
#pragma GCC optimization("unroll-loops")
using namespace std;
template <typename T>
void DBG(const char* name, T&& H) {
  cerr << name << " = " << H << ')' << '\n';
}
template <typename T, typename... Args>
void DBG(const char* names, T&& H, Args&&... args) {
  const char* NEXT = strchr(names + 1, ',');
  cerr.write(names, NEXT - names) << " = " << H << " |";
  DBG(NEXT + 1, args...);
}
using ll = int;
using ld = long double;
const ll mod = 1e9 + 7;
const ld PI = acos(-1.0);
template <typename T>
struct node {
  T mx;
  node(T y = 0) : mx(y){};
};
template <typename T>
struct lazyNode {
  T val;
  lazyNode(T x = 0) : val(x){};
};
struct SGT {
  using S = int;
  using T = long long;
  S size;
  vector<node<T>> data;
  vector<lazyNode<T>> lazy;
  vector<bool> isLazy;
  SGT(S sz = 1e6 + 1) {
    size = 1e6 + 1;
    data.resize(4 * sz);
    lazy.resize(4 * sz);
    isLazy.assign(4 * sz, false);
  }
  void merge(node<T>& pt, node<T>& lc, node<T>& rc) {
    pt.mx = max(lc.mx, rc.mx);
  }
  void push(S pt, S lc, S rc, S l, S r) {
    if (!isLazy[pt]) return;
    if (l != r) {
      isLazy[lc] = 1;
      isLazy[rc] = 1;
      lazy[lc].val = max(lazy[pt].val, lazy[lc].val);
      lazy[rc].val = max(lazy[pt].val, lazy[rc].val);
    }
    data[pt].mx = max(data[pt].mx, lazy[pt].val);
    lazy[pt].val = 0;
    isLazy[pt] = 0;
  }
  node<T> query(S x, S l, S r, S qL, S qR) {
    if (isLazy[x]) {
      push(x, 2 * x, 2 * x + 1, l, r);
    }
    if (qL > qR) {
      return node<T>(0);
    }
    if ((l == qL) && (r == qR)) {
      return data[x];
    }
    S mid = ((l + r) >> 1);
    node<T> res;
    node<T> lc = query(2 * x, l, mid, qL, min(mid, qR));
    node<T> rc = query(2 * x + 1, mid + 1, r, max(mid + 1, qL), qR);
    merge(res, lc, rc);
    return res;
  }
  void update(S x, S l, S r, S qL, S qR, T val) {
    if (isLazy[x]) {
      push(x, 2 * x, 2 * x + 1, l, r);
    }
    if (qL > qR) {
      return;
    }
    if ((l == qL) && (r == qR)) {
      isLazy[x] = 1;
      lazy[x].val = val;
      push(x, 2 * x, 2 * x + 1, l, r);
      return;
    }
    S mid = ((l + r) >> 1);
    update(2 * x, l, mid, qL, min(mid, qR), val);
    update(2 * x + 1, mid + 1, r, max(mid + 1, qL), qR, val);
    merge(data[x], data[2 * x], data[2 * x + 1]);
  }
};
void Solve() {
  ll n;
  cin >> n;
  vector<pair<ll, ll>> cor(n);
  for (ll i = 0; i < n; i++) {
    cin >> cor[i].first >> cor[i].second;
  }
  sort(cor.begin(), cor.end());
  vector<pair<ll, ll>> a(n);
  vector<ll> revMap(n);
  for (ll i = 0; i < n; i++) {
    a[i] = {cor[i].first - cor[i].second, i};
  }
  sort(a.begin(), a.end());
  for (ll i = 0; i < n; i++) {
    revMap[a[i].second] = i;
  }
  SGT sgt(n);
  ll ans = 0;
  for (ll i = 0; i < n; i++) {
    ll idx = revMap[i];
    sgt.update(1, 0, n - 1, idx, idx, 1);
    ll val = sgt.query(1, 0, n - 1, idx, idx).mx;
    ans = max(ans, val);
    ll id = lower_bound(a.begin(), a.end(),
                        make_pair(cor[i].first + cor[i].second, -1)) -
            a.begin();
    if (id == n) continue;
    sgt.update(1, 0, n - 1, id, n - 1, val + 1);
  }
  cout << ans << '\n';
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int tt = 1;
  while (tt--) {
    Solve();
  }
  return 0;
}
