题意:按y=Ax+B的形式给出n(<=50000)条直线,求从y值为无穷大的地方向下看能看到的直线编号
一看到题目就想到半平面交,以每条直线的上方为一个半平面,求半平面的交,交集中存在的直线就是能看到的直线
但是写出来之后发现样例都过不了。。。
对于样例,如果允许半平面在边界处重叠那么答案是1,2,3,如果不允许只有1。。
然后抱着试一试的心理交上去了,结果竟然直接AC了。。
后来看题解只需要考虑交点x坐标。。
c++ code 蒟蒻532ms ORZ前排0msAC的神犇。。。。
/**************************************************************
Problem: 1007
User: Lytning
Language: C++
Result: Accepted
Time:532 ms
Memory:8524 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
const double eps = 1e-8;
int dcmp(double x)
{
if(fabs(x) < eps) return 0;
else return x>0? 1 : -1;
}
#define Vector Point
struct Point
{
double x,y;
Point(double x=0, double y=0):x(x),y(y) {}
};
Vector operator + (Vector A, Vector B) {return Vector(A.x + B.x, A.y + B.y);}
Vector operator - (Vector A, Vector B) {return Vector(A.x - B.x, A.y - B.y);}
Vector operator * (Vector A, double p) {return Vector(A.x * p, A.y * p);}
Vector operator / (Vector A, double p) {return Vector(A.x / p, A.y / p);}
bool operator == (const Vector& A, const Vector& B) {return dcmp(A.x - B.x)==0 && dcmp(A.y - B.y)==0;}
double Cross(Vector A, Vector B)
{
return A.x * B.y - A.y * B.x;
}
struct Line
{
Point P;
Vector v;
double ang;
int num;
Line() {}
Line(int A, int B, int nums)//y=Ax+B
{
double x = 1.0, y = A*x+B;
P = Point(x,y);
x = 2.0, y = A*x+B;
v = Point(x,y) - P;
ang = atan2(v.y, v.x);
num = nums;
}
bool operator < (const Line& L) const
{
return ang < L.ang;
}
}Li[50000+5];;
bool onLeft(Line L, Point P)
{
return Cross(L.v,P-L.P) > 0;
}
inline Point GetIntersection(Line a, Line b)
{
Vector u = a.P - b.P;
double t = Cross(b.v, u) / Cross(a.v, b.v);
return a.P + a.v * t;
}
bool cmp_num(Line a, Line b)
{
return a.num < b.num;
}
void HalfplaneIntersection(Line* L, int n)
{
sort(L,L+n);
Point *p = new Point[n];
Line *q = new Line[n];
int first, last;
q[first = last = 0] = L[0];
for(int i=1; i<n; i++)
{
while(first < last && !onLeft(L[i], p[last-1])) last--;
while(first < last && !onLeft(L[i], p[first])) first++;
q[++last] = L[i];
if(q[last].v == q[last-1].v)
{
last --;
if(onLeft(q[last], L[i].P)) q[last] = L[i];
}
if(first < last) p[last-1] = GetIntersection(q[last-1],q[last]);
}
while(first < last && !onLeft(q[first],p[last-1])) last--;
Line *lines = new Line[n];
int k = 0;
for(int i = first; i<=last; i++)
lines[k++] = q[i];
sort(lines,lines+k,cmp_num);
for(int i = 0; i < k; i++)
cout<<lines[i].num<<" ";
}
int main()
{
//freopen("bz1007.in","r",stdin);freopen("bz1007.out","w",stdout);
int n;
cin>>n;
for(int i = 1; i <= n; i++)
{
int A,B;
cin>>A>>B;
Li[i-1] = Line(A,B,i);
}
HalfplaneIntersection(Li,n);
}