1. 程式人生 > >bzoj 1007 水平可見直線 半平面交稀裡糊塗的過了...

bzoj 1007 水平可見直線 半平面交稀裡糊塗的過了...

題意:按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);
}