BZOJ 1007: [HNOI2008]水平可见直线 栈/计算几何

1007: [HNOI2008]水平可见直线

Time Limit: 1 Sec  Memory Limit: 162 MB

题目连接

http://www.lydsy.com/JudgeOnline/problem.php?id=1007

Description

 在xoy直角坐标平面上有n条直线L1,L2,...Ln,若在y值为正无穷大处往下看,能见到Li的某个子线段,则称Li为可见的,否则Li为被覆盖的.
    例如,对于直线:
    L1:y=x; L2:y=-x; L3:y=0
    则L1和L2是可见的,L3是被覆盖的.
    给出n条直线,表示成y=Ax+B的形式(|A|,|B|<=500000),且n条直线两两不重合.求出所有可见的直线.

Input

第一行为N(0 < N < 50000),接下来的N行输入Ai,Bi

Output

从小到大输出可见直线的编号,两两中间用空格隔开,最后一个数字后面也必须有个空格

Sample Input

3
-1 0
1 0
0 0

Sample Output

1 2

HINT

题解:

首先我们按照斜率从大到小排序,然后我们对一个堆进行优化

如果要插入一条直线的话,K最大的那条线和K最小的肯定不会背盖住,只会有中间的那条直线被压住

所以我们就判定一下,然后不停的更新就好了

具体判定是看 斜率小的直线与斜率中间的直线,斜率小的直线和斜率大的直线,这两个x的坐标大小进行比较,然后就可以啦~

代码:

 

//qscqesze

#include <cstdio>

#include <cmath>

#include <cstring>

#include <ctime>

#include <iostream>

#include <algorithm>

#include <set>

#include <vector>

#include <sstream>

#include <queue>

#include <typeinfo>

#include <fstream>

#include <map>

typedef long long ll;

using namespace std;

//freopen("D.in","r",stdin);

//freopen("D.out","w",stdout);

#define sspeed ios_base::sync_with_stdio(0);cin.tie(0)

#define maxn 50001

#define mod 10007

#define eps 1e-9

//const int inf=0x7fffffff;   //无限大

const int inf=0x3f3f3f3f;

/*



*/

//**************************************************************************************

struct node

{

    double x,y;

    int id;

};

bool cmp(node c,node d)

{

    return c.x>d.x;

}

double kiss(node a,node b)

{

    return (b.y-a.y+0.0)/(a.x-b.x+0.0);

}

node a[maxn],aa[maxn];

int s[maxn];

inline ll read()

{

    int x=0,f=1;char ch=getchar();

    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}

    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}

    return x*f;

}

bool cmp2(int c,int d)

{

    return a[c].id<a[d].id;

}

int main()

{

    int n;

    cin>>n;

    for(int i=1;i<=n;i++)

    {

        cin>>aa[i].x>>aa[i].y;

        aa[i].id=i;

    }

    sort(aa+1,aa+n+1,cmp);

    int M=0;

    for(int i=1;i<=n;i++)

    {

        if(aa[i].x!=a[i-1].x) 

            a[++M]=aa[i];

        else if(aa[i].y>a[M].y) 

            a[M].y=aa[i].y,a[M].id=aa[i].id;            

    }

    int top=0;

    s[1]=1;top=1;

    for(int i=2;i<=M;i++)

    {

        while(top>=2)

        {

            double x1=kiss(a[s[top-1]],a[i]);

            double x2=kiss(a[s[top]],a[i]);

            if(x1<=x2+1e-6)

                top--;

            else

                break;

        }

        s[++top]=i;

    }

    sort(s+1,s+top+1,cmp2);

    for(int i=1;i<=top;i++)

        cout<<a[s[i]].id<<" ";

    return 0;

}

 

你可能感兴趣的:(2008)