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

bzoj1007: [HNOI2008]水平可见直线

时间:2016-07-15 09:29:43      阅读:143      评论:0      收藏:0      [点我收藏+]

标签:

半凸包。完全不会。。膜了黄学长的题解。。。高大上 啊。。。开始的时候const int eps=1e-8 WA了。。。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
#define rep(i,n) for(int i=1;i<=n;i++)
const int nmax=50005;
const double eps=1e-8;
struct edge{
	double a,b;int num;
};
edge edges[nmax];
bool cmp(edge x,edge y){
	if(fabs(x.a-y.a)<eps) return x.b<y.b;
	return x.a<y.a;
}
double crossx(edge x,edge y){
	return (y.b-x.b)/(x.a-y.a);
}
edge s[nmax];
int ans[nmax];
int main(){
	int n;scanf("%d",&n);
	rep(i,n) scanf("%lf%lf",&edges[i].a,&edges[i].b),edges[i].num=i;
	sort(edges+1,edges+n+1,cmp);
	//rep(i,n) printf("%lf ",edges[i].a);
	int top=0;
	rep(i,n) {
		edge o=edges[i];
		while(top){
			if(fabs(s[top].a-o.a)<eps) top--;
			else if(top>1&&crossx(o,s[top-1])<=crossx(s[top],s[top-1])) top--;
			else break;
		}
		s[++top]=o;
	}
	rep(i,top) ans[s[i].num]=1;
	rep(i,n) if(ans[i]) printf("%d ",i);
	return 0;
}

  

1007: [HNOI2008]水平可见直线

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 5749  Solved: 2183
[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

HINT

 

Source

 
[Submit][Status][Discuss]

bzoj1007: [HNOI2008]水平可见直线

标签:

原文地址:http://www.cnblogs.com/fighting-to-the-end/p/5672417.html

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