最后所有可见直线形成的,一定是类似下凸壳的东西,从左到右斜率递增。
将所有直线按照斜率从小到大排序,依次遍历分情况入栈。一条直线会把前一条直线覆盖,当且仅当该直线斜率比前一条直线大(排序后一定满足),且直线在栈中前两条直线的交点之上。这样也就是在维护一个下凸壳。
#include<cstdio>
#include<algorithm>
#include<cmath>
#define MAXN 50005
using namespace std;
struct line{double k, b;int id;}l[MAXN];
double eps=1e-7;
bool cmp(line a, line b){return a.k<b.k||(fabs(a.k-b.k)<eps&&a.b<b.b);}
double crossx(line a, line b){return (b.b-a.b)/(a.k-b.k);}
int S[MAXN], top=0, ans[MAXN];
int main()
{
int n;
scanf("%d",&n);
for(int i = 1; i <= n; i++)
{
scanf("%lf%lf",&l[i].k,&l[i].b);
l[i].id=i;
}
sort(l+1,l+n+1,cmp);
for(int i = 1; i <= n; i++)
{
while(top)
{
if(fabs(l[S[top-1]].k-l[i].k)<eps)top--;
else if(top>1&&crossx(l[i],l[S[top-1]])<=crossx(l[S[top-2]],l[S[top-1]]))top--;
else break;
}
S[top++]=i;
}
for(int i = 0 ; i < top; i++)
ans[l[S[i]].id]=1;
for(int i = 1; i <= n; i++)
if(ans[i])
printf("%d ",i);
return 0;
}