【BZOJ1007】[HNOI2008]水平可见直线 半平面交

【BZOJ1007】[HNOI2008]水平可见直线

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

题解:本人懒,直接用的半平面交。当然由于本题的特殊性质(都是取上半平面),所以我们可以将单调队列换成单调栈。

由于精度问题,本题需要将eps去掉。

 

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn=50010;
const double alpha=1.23456789;
struct point
{
	double x,y;
	point() {}
	point(double a,double b){x=a,y=b;}
	point operator + (const point &a) const {return point(x+a.x,y+a.y);}
	point operator - (const point &a) const {return point(x-a.x,y-a.y);}
	point operator * (const double &a) const {return point(x*a,y*a);}
	double operator * (const point &a) const {return x*a.y-y*a.x;}
};
struct line
{
	point p,v;
	double a;
	int org;
	line() {}
	line(point x,point y,int z){p=x,v=y,a=atan2(v.y,v.x),org=z;}
}l[maxn];
int q[maxn],ans[maxn];
int h,t,n;
point getp(line l1,line l2)
{
	point u=l1.p-l2.p;
	double temp=(l2.v*u)/(l1.v*l2.v);
	return l1.p+l1.v*temp;
}
bool onlft(line a,point b)
{
	return a.v*(b-a.p)>0;
}
bool cmp(line a,line b)
{
	if(fabs(a.a-b.a)==0)	return !onlft(a,b.p);
	return a.a<b.a;
}
void HPI()
{
	sort(l+1,l+n+1,cmp);
	int i,cnt;
	for(i=2,cnt=1;i<=n;i++)	if(fabs(l[i].a-l[cnt].a)>0)	l[++cnt]=l[i];
	h=t=q[1]=1;
	for(i=2;i<=cnt;i++)
	{
		while(h<t&&!onlft(l[i],getp(l[q[t]],l[q[t-1]])))	t--;
		while(h<t&&!onlft(l[i],getp(l[q[h]],l[q[h+1]])))	h++;
		q[++t]=i;
	}
	//while(h<t&&onlft(l[q[h]],getp(l[q[t]],l[q[t-1]])))	t--;
	//while(h<t&&onlft(l[q[t]],getp(l[q[h]],l[q[h+1]])))	h++;
}
int main()
{
	scanf("%d",&n);
	int i;
	double a,b;
	for(i=1;i<=n;i++)	scanf("%lf%lf",&a,&b),l[i]=line(point(0,b),point(1,a),i);
	HPI();
	for(i=h;i<=t;i++)	ans[++ans[0]]=l[q[i]].org;
	sort(ans+1,ans+ans[0]+1);
	for(i=1;i<=ans[0];i++)	printf("%d ",ans[i]);
	return 0;
}

 

posted @ 2017-09-10 11:36  CQzhangyu  阅读(313)  评论(0编辑  收藏  举报