BZOJ #1007. [HNOI2008]水平可见直线

比较简单的计算几何题,但是刚开始漏想了一种情况还写了个假算法的说

容易发现如果我们给所有的直线看成一个向\(y=\infty\)方向的半平面,那么求一个半平面交就可以得到能看到的上方部分的直线了

由于这里的半平面性质比较好(同开口方向),直接按斜率排序后用单调栈维护一下即可,注意处理好斜率相同的情况

#include<cstdio>
#include<algorithm>
#define RI register int
#define CI const int&
using namespace std;
const int N=50005;
struct line
{
	int k,b,id;
	friend inline bool operator < (const line& A,const line& B)
	{
		return A.k!=B.k?A.k<B.k:A.b>B.b;
	}
}l[N]; int n,x,y,stk[N],top,ans[N];
inline double getx(const line& A,const line& B)
{
	if (A.k==B.k) return -1e9; return 1.0*(B.b-A.b)/(A.k-B.k);
}
int main()
{
	RI i; for (scanf("%d",&n),i=1;i<=n;++i) scanf("%d%d",&l[i].k,&l[i].b),l[i].id=i;
	for (sort(l+1,l+n+1),i=1;i<=n;++i)
	{
		if (top&&l[stk[top]].k==l[i].k) continue;
		while (top>1&&getx(l[stk[top]],l[i])<=getx(l[stk[top]],l[stk[top-1]])) --top;
		stk[++top]=i;
	}
	for (i=1;i<=top;++i) ans[i]=l[stk[i]].id;
	for (sort(ans+1,ans+top+1),i=1;i<=top;++i) printf("%d ",ans[i]);
	return 0;
}
posted @ 2020-10-29 08:55  空気力学の詩  阅读(95)  评论(0编辑  收藏  举报