【bzoj 1007】水平可见直线(凸包)

来源:互联网 发布:钩针设计软件 编辑:程序博客网 时间:2024/05/17 08:38

传送门biu~
先按斜率排序,将两条线入栈,依次添加每条直线,如果与栈顶直线的交点在上一个交点的左边,弹栈。这样就可以维护一个开口向上的半凸包。这是因为对于一个开口向上的半凸包,从左向右看,直线的斜率是递增的,点的x坐标也都是递增的。

#include<bits/stdc++.h>using namespace std;struct point{    double x,y;    point(double _=0,double __=0){x=_;y=__;}};struct line{    int num;    double k,b;    bool operator< (const line&r) const{        return (k<r.k) || (k==r.k && b<r.b);    }    point operator ^(const line&r) const{        double x=(r.b-b)/(k-r.k);        double y=k*x+b;        return point(x,y);    }}stac[100005],lines[100005];bool cmp(line a,line b){return a.num<b.num;}int main(){    int n,top=0;    scanf("%d",&n);    for(int i=1;i<=n;++i)    scanf("%lf%lf",&lines[i].k,&lines[i].b),lines[i].num=i;    sort(lines+1,lines+n+1);    double x=0;    for(int i=1;i<=n;++i){        while(abs(lines[i+1].k-lines[i].k)<=1e-9 && i+1<=n)   ++i;        double nx=0;        if(top) nx=(lines[i]^stac[top]).x;        while(nx-x<=1e-9 && top>=2){            --top;            if(top!=1)  x=(stac[top]^stac[top-1]).x;            nx=(lines[i]^stac[top]).x;        }        x=nx;        stac[++top]=lines[i];    }    sort(stac+1,stac+top+1,cmp);    for(int i=1;i<=top;++i)      printf("%d ",stac[i].num);    return 0;}