bzoj 1007 水平可见直线

bzoj 1007 水平可见直线

  • 这里的半平面都是 (ygeq kx+b) 类型的,将直线 (l:y=kx+b) 对应到点 ((k,-b)) ,转化成凸包求解即可.
  • 如果有两种类型,需分类后分别求上下凸包,最后去重,合并.
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair
#define pii pair<int,int>
inline int read()
{
	int x=0;
	bool pos=1;
	char ch=getchar();
	for(;!isdigit(ch);ch=getchar())
		if(ch=='-')
			pos=0;
	for(;isdigit(ch);ch=getchar())
		x=x*10+ch-'0';
	return pos?x:-x;
}
const double eps=1e-10;
const int MAXN=5e4+10;
int n;
struct Line{
	int k,b;
	int id;
	bool operator < (const Line &rhs) const 
		{
			return (k<rhs.k)||(k==rhs.k&&b>rhs.b);
		}
	Line operator - (const Line &rhs) const
		{
			Line res;
			res.k=k-rhs.k;
			res.b=b-rhs.b;
			return res;
		}
}A[MAXN];
int stk[MAXN],tp=0;
double calck(Line x,Line y)
{
	return 1.0*(y.b-x.b)/(x.k-y.k);
}
int ans[MAXN];
int main()
{
	n=read();
	for(int i=1;i<=n;++i)
		{
			A[i].k=read();
			A[i].b=read();
			A[i].id=i;
		}
	sort(A+1,A+1+n);
	stk[++tp]=1;
	for(int i=2;i<=n;++i)
		if(A[i].k!=A[i-1].k)
			{
				while(tp>=2 && calck(A[i],A[stk[tp]])-calck(A[stk[tp]],A[stk[tp-1]])<=eps)
					--tp;
				stk[++tp]=i;
			}	
	for(int i=1;i<=tp;++i)
		ans[i]=(A[stk[i]].id);
	sort(ans+1,ans+1+tp);
	for(int i=1;i<=tp;++i)
		printf("%d ",ans[i]);
	puts("");
	return 0;
}
原文地址:https://www.cnblogs.com/jklover/p/10388839.html