Solution Notes: There are several ways to approach this problem that lead to O(N) or O(N log N) solutions (O(N^2) isn't quite fast enough to solve all of the cases in time). To start with, there are really two interesting cases to check: either the points can all be covered by 3 horizontal lines, or by 2 horizontal lines and 1 vertical line. There are two other cases symmetric to these, but we can easily transform them into the two previous cases by swapping x and y for each point. In Richard's code below, he uses an STL map to store a "histogram" of how many times each distinct y coordinate appears, as well as the total number of distinct y coordinates. When a point is added to this data structure, its count is incremented (and if the count was previously zero, then we also increment the number of distinct y coordinates in total). When a point is removed from the data structure, its count is decremented (and if the count is now zero, we also decrement the total number of distinct y coordinates). Now to test if all our points can be covered with 3 horizontal lines, we add them all to our structure and check if the count of the total number of distinct y coordinates is at most 3. To test if 2 horizontal lines and 1 vertical line are sufficient, we sort the points on x, and for each distinct x coordinate, we temporarily remove all the points having that x coordinate and test if the number of distinct y coordinates drops to at most 2.


#include <cstdio>
#include <cstring>
#include <map>
#include <algorithm>
using namespace std;

const int MAXN = 1001000;

pair<int,int> lis[MAXN];
map<int, int> cou;
int distinct;
int n;

void inc(int x) {
	if(cou[x] == 0) {
		distinct++;
	}
	cou[x] = cou[x] + 1;
}

void dec(int x) {
	cou[x] = cou[x] - 1;
	if(cou[x] == 0) {
		distinct--;
	}
}

int moo() {
	sort(lis, lis + n);
	distinct = 0;
	cou.clear();
	for(int i = 0; i < n; ++i) {
		inc(lis[i].second);
	}
	if(distinct <= 3) return 1;
	int i = 0, i1 = 0;
	while(i < n) {
		while(i1 < n && lis[i].first == lis[i1].first) {
			i1++;
		}
		for(int i2 = i; i2 < i1; ++i2) {
			dec(lis[i2].second);
		}
		if(distinct <= 2)  return 1;
		for(int i2 = i; i2 < i1; ++i2) {
			inc(lis[i2].second);
		}
		i = i1;
	}
	return 0;
}

int main() {
        freopen("3lines.in", "r", stdin);
        freopen("3lines.out", "w", stdout);
	scanf("%d", &n);
	for(int i = 0; i < n; ++i) {
		scanf("%d%d", &lis[i].first, &lis[i].second);
	}
	if(moo()) {
		puts("1");
	}
	else {
		for(int i = 0; i < n; ++i) {
			swap(lis[i].first, lis[i].second);
		}
		if(moo()) {
			puts("1");
		}
		else {
			puts("0");
		}
	}
	return 0;
}