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;
}
``````