#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <algorithm>
#include <numeric>
#include <random>
#include <vector>
#include <array>
#include <bitset>
#include <queue>
#include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>

using namespace std;
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
template<class T> using V = vector<T>;
template<class T> using VV = V<V<T>>;
constexpr ll TEN(int n) { return (n==0) ? 1 : 10*TEN(n-1); }


int rand_int(int a, int b) {
    static random_device rd;
    static mt19937 gen(rd());
    return uniform_int_distribution<int>(a, b)(gen);
}

int z;


struct NodeX {
    using NP = NodeX*;
    NP l = nullptr, r = nullptr;
    int sz;
    int mi;
    void refl() {
        if (l == nullptr) {
            l = new NodeX(sz/2);
        }        
    }
    void refr() {
        if (r == nullptr) {
            r = new NodeX(sz-sz/2);
        }        
    }
    void ref() {
        refl(); refr();
    }
    int get(int a) { // a <= x && b <= y
        if (a <= 0) return mi;
        if (sz <= a) return 0;
        int ma = 0;
        if (l != nullptr) ma = max(ma, l->get(a));
        if (r != nullptr) ma = max(ma, r->get(a - sz/2));
        return ma;
    }
    void setd(int a, int x) {
        if (sz == 1) {
            mi = max(mi, x);
            return;
        }
        if (a < sz/2) {
            refl();
            l->setd(a, x);
        } else {
            refr();
            r->setd(a-sz/2, x);
        }
        mi = 0;
        if (l != nullptr) mi = max(mi, l->mi);
        if (r != nullptr) mi = max(mi, r->mi);
    }
    NodeX(int sz) : sz(sz) {
        mi = 0;
    }
};

struct NodeY {
    using NP = NodeY*;
    NP l, r;
    int sz;
    V<int> fi;
    NodeX* mi;
    void pre(int a, int b) {
        fi.push_back(a);
        if (sz == 1) return;
        if (b < sz/2) {
            l->pre(a, b);
        } else {
            r->pre(a, b-sz/2);
        }
    }
    void fin() {
        sort(begin(fi), end(fi));
        fi.erase(unique(begin(fi), end(fi)), end(fi));
        mi = new NodeX(int(fi.size()));
        if (sz == 1) return;
        l->fin(); r->fin();
    }
    int get(int a, int b) { // a <= x && b <= y
        if (b <= 0) {
            int aid = lower_bound(begin(fi), end(fi), a) - begin(fi);
            return mi->get(aid);
        }
        if (sz <= b) return 0;
        return max(l->get(a, b), r->get(a, b - sz/2));
    }
    void setd(int a, int b, int x) {
        int aid = lower_bound(begin(fi), end(fi), a) - begin(fi);
        mi->setd(aid, x);

        if (sz == 1) return;
        if (b < sz/2) {
            l->setd(a, b, x);
        } else {
            r->setd(a, b-sz/2, x);
        }
    }
    NodeY(int sz) : sz(sz) {
//        mi = new NodeX(z);
        if (sz == 1) return;
        l = new NodeY(sz/2);
        r = new NodeY(sz-sz/2);
    }
};

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << setprecision(20);
    int n;
    cin >> n;
    using P = pair<int, int>;
    V<P> v(n);
    for (int i = 0; i < n; i++) {
        int l, r;
        cin >> l >> r;
        v[i] = P(l, r);
    }
    sort(begin(v), end(v), [&](P l, P r){
        return l.first+l.second > r.first+r.second;
    });
    V<int> xv;
    for (int i = 0; i < n; i++) {
        xv.push_back(v[i].first);
        xv.push_back(v[i].second);
    }
    sort(begin(xv), end(xv));
    xv.erase(unique(begin(xv), end(xv)), end(xv));
    for (int i = 0; i < n; i++) {
        v[i].first = lower_bound(begin(xv), end(xv), v[i].first) - begin(xv);
        v[i].second = lower_bound(begin(xv), end(xv), v[i].second) - begin(xv);
    }
    z = int(xv.size()) + 2;

    NodeY* tr = new NodeY(z);
    V<int> a(n);
    int ans = 0;
    for (int i = 0; i < n; i++) {
        auto p = v[i];
        tr->pre(p.second+1, p.first+1);
        tr->pre(p.first, p.second);
    }
    tr->fin();
    for (int i = 0; i < n; i++) {
        auto p = v[i];
        auto p2 = P(p.second, p.first);
        a[i] = 1 + tr->get(p.second+1, p.first+1);
        tr->setd(p.first, p.second, a[i]);
        ans = max(ans, a[i]);
    }
    cout << ans << endl;
    return 0;
}

Measured memory_bytes: 206892