void solve(){
int N; cin >> N;
vector<pii> points(N);
vector<int> xs, ys;
rep(i, 0, N){
int x, y; cin >> x >> y;
points[i] = {x, y};
xs.push_back(x);
ys.push_back(y);
}
sort(all(xs)); xs.erase(unique(all(xs)), xs.end());
sort(all(ys)); ys.erase(unique(all(ys)), ys.end());
rep(i, 0, N){
points[i].first = lower_bound(all(xs), points[i].first) - xs.begin();
points[i].second = lower_bound(all(ys), points[i].second) - ys.begin();
}
vector<vector<bool>> isPoint(xs.size(), vector<bool>(ys.size()));
for(auto [x, y] : points) isPoint[x][y] = true;
int ans = 0;
vector<vector<int>> DP(ys.size(), vector<int>(ys.size()));
rrep(i, 0, xs.size()){
vector<vector<int>> cur_cnt(ys.size(), vector<int>(ys.size())); // cur_cnt[j][k] = j, k 사이에 있는 점의 개수
rep(j, 0, ys.size()){
if(isPoint[i][j]) cur_cnt[j][j]++;
rep(k, j+1, ys.size()) cur_cnt[j][k] = cur_cnt[j][k-1] + isPoint[i][k];
}
rep(j, 0, ys.size()) rep(k, j+1, ys.size()){
ans = max(ans, cur_cnt[j][k] + DP[j][k]);
DP[j][k] = max(DP[j][k] + isPoint[i][j] + isPoint[i][k], cur_cnt[j][k]);
}
}
// 세로 한줄 처리
rep(i, 0, ys.size()){
int cnt = 0;
rep(j, 0, xs.size()) if(isPoint[j][i]) cnt++;
ans = max(ans, cnt);
}
cout << ans;
}