#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 3;
typedef pair <int, int> ii;
vector<int> node[N], ft[N];
ii vA[N];
int n;
void update(vector<int> &ft, int pos, int val) {
for ( ; pos <= ft.size(); pos += (pos & -pos)) {
ft[pos] = max(ft[pos], val);
}
}
int get(vector<int> &ft, int pos) {
int ans = 0;
for ( ; pos > 0; pos -= (pos & -pos)) {
ans = max(ans, ft[pos]);
}
return ans;
}
int main() {
ios_base::sync_with_stdio(0);
cin.tie(NULL);
cin >> n;
vector<int> vX(n), vY(n);
for (int i = 1; i <= n; ++i) {
cin >> vX[i - 1] >> vY[i - 1];
vA[i] = {vX[i - 1], vY[i - 1]};
}
sort(vX.begin(), vX.end());
sort(vY.begin(), vY.end());
for (int i = 1; i <= n; ++i) {
vA[i].first = (int) (lower_bound(vX.begin(), vX.end(), vA[i].first) - vX.begin()) + 1;
vA[i].second = (int) (lower_bound(vY.begin(), vY.end(), vA[i].second) - vY.begin()) + 1;
// Fake GET
for (int j = vA[i].first - 1; j > 0; j -= (j & -j)) {
node[j].push_back(vA[i].second);
}
// FAke update
for (int j = vA[i].first; j <= n; j += (j & -j)) {
node[j].push_back(vA[i].second);
}
}
for (int i = 1; i <= n; ++i) {
node[i].push_back(10000032);
sort(node[i].begin(), node[i].end());
node[i].erase(unique(node[i].begin(), node[i].end()), node[i].end());
ft[i].resize(node[i].size() + 1, 0);
}
int ans = 0;
for (int i = 1; i <= n; ++i) {
int x = vA[i].first, y = vA[i].second;
int tmp = 1;
for (int j = x - 1; j > 0; j -= (j & -j)) {
int currentY = (int) (lower_bound(node[j].begin(), node[j].end(), y) - node[j].begin()) + 1;
tmp = max(tmp, get(ft[j], currentY - 1) + 1);
}
for (int j = x; j <= n; j += (j & -j)) {
int currentY = (int) (lower_bound(node[j].begin(), node[j].end(), y) - node[j].begin()) + 1;
update(ft[j], currentY, tmp);
}
ans = max(ans, tmp);
/* cerr << tmp << '\n'; */
}
cout << ans << '\n';
return 0;
}