#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MAXN = 1e5 + 5;
const int INF = 1e18;
int n;
int x[MAXN], y[MAXN], d1[MAXN], d2[MAXN];
map<int, set<pair<int,int>>> of_d1, of_d2, of_x, of_y;
void baga(int id)
{
of_d1[d1[id]].insert({x[id], id});
of_d2[d2[id]].insert({x[id], id});
of_x[x[id]].insert({y[id], id});
of_y[y[id]].insert({x[id], id});
}
void scoate(int id)
{
of_d1[d1[id]].erase({x[id], id});
of_d2[d2[id]].insert({x[id], id});
of_x[x[id]].erase({y[id], id});
of_y[y[id]].erase({x[id], id});
}
int dist[MAXN];
priority_queue<pair<int, pair<int,int>>> pq;//{-dist, {nod, dir}}
vector<int> aux;
void add_to_pq(int nod, int dir, int t)
{
if(dist[nod] <= t)
return;
aux.push_back(nod);
dist[nod] = t;
pq.push({-dist[nod], {nod, dir}});
}
int solve(int root_dir)
{
for(int i=1;i<=n;i++)
{
dist[i] = INF;
baga(i);
}
while(!pq.empty())
pq.pop();
add_to_pq(1, root_dir, 0);
while(!pq.empty())
{
int cdist = -pq.top().first, nod = pq.top().second.first, dir = pq.top().second.second;
pq.pop();
assert(cdist == dist[nod]);
if(cdist != dist[nod])
continue;
//add equal x and y cases-------------------------------------------------------------
baga(nod);
aux.clear();
auto it1 = of_d1[d1[nod]].find({x[nod], nod});
auto it2 = of_d2[d2[nod]].find({x[nod], nod});
if(dir == 0)
{
while(1)
{
it1++;
if(it1 == of_d1[d1[nod]].end())
break;
int ct = (*it1).first - x[nod];
if(ct >= dist[nod]) add_to_pq((*it1).second, 3, ct);
}
while(1)
{
it2++;
if(it2 == of_d2[d2[nod]].end())
break;
int ct = (*it2).first - x[nod];
if(ct >= dist[nod]) add_to_pq((*it2).second, 2, ct);
}
}
else if(dir == 1)
{
while(1)
{
if(it1 == of_d1[d1[nod]].begin())
break;
it1--;
int ct = x[nod] - (*it1).first;
if(ct >= dist[nod]) add_to_pq((*it1).second, 2, ct);
}
while(1)
{
if(it2 == of_d2[d2[nod]].begin())
break;
it2--;
int ct = x[nod] - (*it2).first;
if(ct >= dist[nod]) add_to_pq((*it2).second, 3, ct);
}
}
else if(dir == 2)
{
while(1)
{
it1++;
if(it1 == of_d1[d1[nod]].end())
break;
int ct = (*it1).first - x[nod];
if(ct >= dist[nod]) add_to_pq((*it1).second, 1, ct);
}
while(1)
{
if(it2 == of_d2[d2[nod]].begin())
break;
it2--;
int ct = x[nod] - (*it2).first;
if(ct >= dist[nod]) add_to_pq((*it2).second, 0, ct);
}
}
else
{
assert(dir == 3);
while(1)
{
if(it1 == of_d1[d1[nod]].begin())
break;
it1--;
int ct = x[nod] - (*it1).first;
if(ct >= dist[nod]) add_to_pq((*it1).second, 0, ct);
}
while(1)
{
it2++;
if(it2 == of_d2[d2[nod]].end())
break;
int ct = (*it2).first - x[nod];
if(ct >= dist[nod]) add_to_pq((*it2).second, 1, ct);
}
}
scoate(nod);
for(int v:aux)
scoate(v);
}
int cnt = 0;
for(int i=1;i<=n;i++)
if(dist[i] < INF)
cnt++;
return cnt;
}
signed main()
{
ios_base::sync_with_stdio(0);cin.tie(0);
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>x[i]>>y[i];
d1[i] = x[i] + y[i];
d2[i] = x[i] - y[i];
baga(i);
}
int mxm = 0;
for(int dir=0;dir<4;dir++)
mxm = max(mxm, solve(dir));
cout<<mxm;
return 0;
}