题目:
http://61.187.179.132/JudgeOnline/problem.php?id=1007 首先,将每条直线按斜率排序,斜率一样的可以把截距小的直线直接排除了(显然)。
接着,按排序后的顺序维护一个栈。
维护方法:求即将入栈的这条直线与栈顶直线求交点,若交点在栈顶直线与栈内第二条直线(从顶数起)交点的左侧,则栈顶直线退栈并再次执行此操作,直到交点在右侧,这条直线入栈。
最后,栈中剩下的直线就是能看见的直线。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
using namespace std;
const int MaxN=50050;
const double oo=1000001;

struct line


{
double a,b;
int num;
};

int n;
line c[MaxN];
bool v[MaxN];
int st1[MaxN],top=0;
double st2[MaxN];

bool cmp(line a,line b)


{
if (a.a<b.a)

{
return 1;
}
if (a.a>b.a)

{
return 0;
}
return a.b>b.b;
}

double x(double x1,double y1,double x2,double y2)


{
return x1*y2-x2*y1;
}
// A B C D
double getjiao(double x1,double y1,double x2,double y2,double x3,double y3,double x4,double y4)


{
double t=x(x2-x1,y2-y1,x3-x1,y3-y1)/x(x4-x1,y4-y1,x2-x1,y2-y1);
return x3+t*(x4-x3);
}

void work()


{
st1[0]=0;
st2[0]=oo;
v[c[0].num]=1;
top=0;
for (int i=1;i<n;i++)

{
if (c[i].a==c[i-1].a)

{
continue;
}
while (1)

{
double k=getjiao(-oo,c[i].a*(-oo)+c[i].b,oo,c[i].a*oo+c[i].b,-oo,c[st1[top]].a*(-oo)+c[st1[top]].b,oo,c[st1[top]].a*oo+c[st1[top]].b);
if (k>st2[top] || top==0)

{
top++;
st1[top]=i;
st2[top]=k;
v[c[i].num]=1;
break;
}
if (k<=st2[top])

{
v[c[st1[top]].num]=0;
top--;
}
}
}
}

int main()


{
cin>>n;
for (int i=0;i<n;i++)

{
cin>>c[i].a>>c[i].b;
c[i].num=i;
v[i]=0;
}
sort(c,c+n,cmp);
work();
for (int i=0;i<n;i++)

{
if (v[i]==1)

{
cout<<i+1<<' ';
}
}
cout<<endl;
return 0;
}
