题目
http://www.lydsy.com/JudgeOnline/problem.php?id=1007
题解
调了一上午最后竟然是我的模板打错了555
半平面交裸题,把所有线段进行半平面交(开口向上),然后看哪些直线在半平面上出现了
听说正解是用单调栈,就是把所有直线按照斜率排序,然后计算几何各种乱搞。。具体百度吧
代码
#include <cstdio>
#include <algorithm>
#include <cmath>
#define maxn 60000
#define finf 1e60
using namespace std;
int N, seen[maxn], cnt;
struct point{double x,y;};
struct vec
{
point a, b;
double th;
int id;
void calc(){th=atan2(b.y-a.y,b.x-a.x);}
}q[maxn], seg[maxn];
double operator*(vec v1, vec v2)
{return (v1.b.x-v1.a.x)*(v2.b.y-v2.a.y)-(v2.b.x-v2.a.x)*(v1.b.y-v1.a.y);}
bool in(point p, vec v){return (vec){v.a,p}*v<0;}
bool operator<(vec v1, vec v2){return v1.th==v2.th?in(v1.a,v2):v1.th<v2.th;}
point cross(vec v1, vec v2)
{
double k1, k2, b1, b2, x, y;
k1=(v1.a.y-v1.b.y)/(v1.a.x-v1.b.x);
k2=(v2.a.y-v2.b.y)/(v2.a.x-v2.b.x);
b1=-k1*v1.a.x+v1.a.y;
b2=-k2*v2.a.x+v2.a.y;
if(v1.a.x==v1.b.x)x=v1.a.x,y=x*k2+b2;
else if(v2.a.x==v2.b.x)x=v2.a.x,y=x*k1+b1;
else x=(b2-b1)/(k1-k2),y=k1*x+v1.a.y;
return (point){x,y};
}
void input()
{
int i;
double k, b;
point p1, p2, p3, p4;
scanf("%d",&N);
for(i=1;i<=N;i++)
{
scanf("%lf%lf",&k,&b);
seg[i]=(vec){(point){0,b},(point){1,k+b}};
seg[i].id=i;
}
p1=(point){finf,finf};
p2=(point){-finf,finf};
p3=(point){-finf,-finf};
p4=(point){finf,-finf};
seg[N+1]=(vec){p1,p2};
seg[N+2]=(vec){p2,p3};
seg[N+3]=(vec){p3,p4};
seg[N+4]=(vec){p4,p1};
cnt=N+4;
}
void hpi()
{
int i, x, l ,r;
for(i=1;i<=cnt;i++)seg[i].calc();
sort(seg+1,seg+cnt+1);
for(i=2,x=1;i<=cnt;i++)if(seg[i].th!=seg[i-1].th)seg[++x]=seg[i];
cnt=x;
q[l=r=1]=seg[1];
for(i=2;i<=cnt;i++)
{
while(l<r and !in(cross(q[r],q[r-1]),seg[i]))r--;
while(l<r and !in(cross(q[l],q[l+1]),seg[i]))l++;
q[++r]=seg[i];
}
while(l<r and !in(cross(q[r],q[r-1]),q[l]))r--;
while(l<r and !in(cross(q[l],q[l+1]),q[r]))l++;
for(i=l;i<=r;i++)seen[q[i].id]=1;
}
int main()
{
input();
hpi();
for(int i=1;i<=N;i++)if(seen[i])printf("%d ",i);
return 0;
}