#include <bits/stdc++.h>
using namespace std;
struct point {
int x, y;
};
enum dir {
RIGHT,
LEFT,
UP,
DOWN
};
enum linetype {
X_PLUS_Y,
X_MINUS_Y
};
enum onwhat {
ON_X,
ON_Y
};
struct maptype {
linetype linetyp;
onwhat onwha;
dir direction;
bool operator<(const maptype &r) const {
if (linetyp != r.linetyp) {
return linetyp < r.linetyp;
}
if (onwha != r.onwha) {
return onwha < r.onwha;
}
return direction < r.direction;
}
};
int solve(int n, vector<point> a) {
vector<dir> dirs = {RIGHT};
for (int i = 1; i < n; ++i) {
auto [x, y] = a[i];
if (x >= 0 && y >= 0) {
dirs.push_back(y < x ? LEFT : DOWN);
} else if (x >= 0 && y < 0) {
dirs.push_back(x > -y ? LEFT : UP);
} else if (x < 0 && y >= 0) {
dirs.push_back(y > -x ? DOWN : RIGHT);
} else {
dirs.push_back(-y > -x ? UP : RIGHT);
}
}
map<maptype, map<int, set<pair<int, int>>>> mps;
for (int i = 0; i < n; ++i) {
auto [x, y] = a[i];
mps[{X_MINUS_Y, ON_X, dirs[i]}][x - y].insert({x, i});
mps[{X_MINUS_Y, ON_Y, dirs[i]}][x - y].insert({y, i});
mps[{X_PLUS_Y, ON_X, dirs[i]}][x + y].insert({x, i});
mps[{X_PLUS_Y, ON_Y, dirs[i]}][x + y].insert({y, i});
}
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
pq.push({0, 0});
vector<int> vis(n);
while (!pq.empty()) {
auto [t, i] = pq.top();
pq.pop();
if (vis[i]) {
continue;
}
vis[i] = 1;
vector<int> rem;
vector<pair<int, int>> rem2;
auto [x, y] = a[i];
auto add = [&](int dist, std::set<std::pair<int, int>>::iterator it) {
if (dist < t) {
rem2.push_back(*it);
} else {
rem.push_back(it->second);
pq.push({t + dist, it->second});
}
};
auto process_rem2 = [&](std::set<std::pair<int, int>> &st) {
for (auto &i : rem2) {
st.erase(i);
}
rem2.clear();
};
if (dirs[i] == RIGHT) {
// on line x-y with their y >= our y
auto &st1 = mps[{X_MINUS_Y, ON_Y, DOWN}][x - y];
for (auto it = st1.lower_bound({y, -1}); it != st1.end(); ++it) {
add(it->first - y, it);
}
process_rem2(st1);
// on line x+y with their y <= our y
auto &st2 = mps[{X_PLUS_Y, ON_Y, UP}][x + y];
for (auto it = st2.begin(), it2 = st2.upper_bound({y, n}); it != it2; ++it) {
add(y - it->first, it);
}
process_rem2(st2);
} else if (dirs[i] == DOWN) {
// on line x-y with their x <= our x
auto &st1 = mps[{X_MINUS_Y, ON_X, RIGHT}][x - y];
for (auto it = st1.begin(), it2 = st1.upper_bound({x, n}); it != it2; ++it) {
add(x - it->first, it);
}
process_rem2(st1);
// on line x+y with their x >= our x
auto &st2 = mps[{X_PLUS_Y, ON_X, LEFT}][x + y];
for (auto it = st2.lower_bound({x, -1}); it != st2.end(); ++it) {
add(it->first - x, it);
}
process_rem2(st2);
} else if (dirs[i] == LEFT) {
// on line x+y with their y >= our y
auto &st1 = mps[{X_PLUS_Y, ON_Y, DOWN}][x + y];
for (auto it = st1.lower_bound({y, -1}); it != st1.end(); ++it) {
add(it->first - y, it);
}
process_rem2(st1);
// on line x-y with their y <= our y
auto &st2 = mps[{X_MINUS_Y, ON_Y, UP}][x - y];
for (auto it = st2.begin(), it2 = st2.upper_bound({y, n}); it != it2; ++it) {
add(y - it->first, it);
}
process_rem2(st2);
} else { // UP
// on line x-y with their x >= our x
auto &st1 = mps[{X_MINUS_Y, ON_X, LEFT}][x - y];
for (auto it = st1.lower_bound({x, -1}); it != st1.end(); ++it) {
add(it->first - x, it);
}
process_rem2(st1);
// on line x+y with their x <= our x
auto &st2 = mps[{X_PLUS_Y, ON_X, RIGHT}][x + y];
for (auto it = st2.begin(), it2 = st2.upper_bound({x, n}); it != it2; ++it) {
add(x - it->first, it);
}
process_rem2(st2);
}
// right left up down
for (auto &mp : mps) {
for (int &i : rem) {
auto [x, y] = a[i];
if (mp.first.linetyp == X_PLUS_Y) {
if (mp.first.onwha == ON_X) {
mp.second[x + y].erase({x, i});
} else {
mp.second[x + y].erase({y, i});
}
} else {
if (mp.first.onwha == ON_X) {
mp.second[x - y].erase({x, i});
} else {
mp.second[x - y].erase({y, i});
}
}
}
}
}
return accumulate(vis.begin(), vis.end(), 0);
}
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int n;
cin >> n;
vector<point> a(n);
for (auto &[x, y] : a) {
cin >> x >> y;
}
for (auto &[x, y] : a | views::drop(1)) {
x -= a[0].x, y -= a[0].y;
}
a[0] = {0, 0};
auto rotate = [&]() {
for (auto &[x, y] : a) {
int nx = y, ny = -x;
x = nx, y = ny;
}
};
int ans = solve(n, a);
rotate();
ans = max(ans, solve(n, a));
rotate();
ans = max(ans, solve(n, a));
rotate();
ans = max(ans, solve(n, a));
cout << ans << '\n';
}