码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 1007: [HNOI2008]水平可见直线

时间:2017-10-13 17:01:46      阅读:137      评论:0      收藏:0      [点我收藏+]

标签:平面   limit   smart   直线   clu   空格   枚举   amp   必须   

1007: [HNOI2008]水平可见直线

Time Limit: 1 Sec  Memory Limit: 162 MB

Submit: 7769  Solved: 2973

[Submit][Status][Discuss]

Description

  在xoy直角坐标平面上有n条直线L1,L2,...Ln,若在y值为正无穷大处往下看,能见到Li的某个子线段,则称Li为
可见的,否则Li为被覆盖的.
例如,对于直线:
L1:y=x; L2:y=-x; L3:y=0
则L1和L2是可见的,L3是被覆盖的.
给出n条直线,表示成y=Ax+B的形式(|A|,|B|<=500000),且n条直线两两不重合.求出所有可见的直线.

Input

  第一行为N(0 < N < 50000),接下来的N行输入Ai,Bi

Output

  从小到大输出可见直线的编号,两两中间用空格隔开,最后一个数字后面也必须有个空格

Sample Input

3
-1 0
1 0
0 0

Sample Output

1 2

题解

按斜率排序后,从小到大枚举,用栈维护当前可见的直线,如果当前考虑的直线和栈顶直线的交点在栈顶直线与栈顶第二条直线的交点的左侧,那么栈顶直线一定看不见,弹出。

因为要用栈顶第二条直线,用手写栈即可。

注意处理精度问题。

代码

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
const int N=500005;
const double eps=1e-8;
int n,top;
struct line{
	int id;
	double a,b;
}l[N],st[N];
bool cmp1(line a,line b){
	if(fabs(a.a-b.a)<=eps)return a.b<b.b;
	return a.a<b.a;
}
bool cmp2(line a,line b){
	return a.id<b.id;
}
double cross(line a,line b){
	return (b.b-a.b)/(a.a-b.a);
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%lf%lf",&l[i].a,&l[i].b);
		l[i].id=i;
	}
	sort(l+1,l+n+1,cmp1);
	for(int i=1;i<=n;i++){
		while(top){
			if(fabs(l[i].a-st[top].a)<=eps)top--;
			else if(top>1&&cross(l[i],st[top-1])<=cross(st[top],st[top-1]))top--;
			else break;
		}
		st[++top]=l[i];
	} 
	sort(st+1,st+top+1,cmp2);
	for(int i=1;i<=top;i++){
		printf("%d ",st[i].id);
	}
	printf("\n");
	return 0;
}

BZOJ 1007: [HNOI2008]水平可见直线

标签:平面   limit   smart   直线   clu   空格   枚举   amp   必须   

原文地址:http://www.cnblogs.com/chezhongyang/p/7661809.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!