USACO2011Open Bronze 3lines 题解

[思路]
符合 FJ的要求有两种情况:三条直线平行或者两条直线平行并与一条直线垂直.至于横竖的问题,可以通过反转奶牛的坐标转化成相同的方式.

三条平行直线:

把所有点的横坐标记录下来,如果不同的横坐标个数小于等于3,那么符合条件.

两条平行与一条直线垂直:
把所有的纵坐标和它们个数记下,也记下所有出现的纵坐标个数,再按照横坐标排序,再枚举一个横坐标a,表示这条直线x=a与其他两条横线垂直,再把这条直线上的所有纵坐标cnt--,再看纵坐标出现的个数,如果<=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() {
	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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值