[BZOJ1007][HNOI2008]水平可见直线 计算几何

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1007

可以发现题目求的就是一个下凸包,把直线按斜率排序,再来维护凸包就好了。可以发现下凸包上的拐点横坐标单增。同时注意处理斜率相同的直线的情况。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const double eps=1e-14;
 6 int inline sign(double x){
 7     return x<-eps?-1:(x>eps?1:0);
 8 }
 9 struct LINE{
10     double A,B;
11     int num;
12     bool operator < (const LINE &_)const{
13         if(sign(A-_.A)) return sign(A-_.A)<0;
14         return sign(B-_.B)>0;
15     }
16 }l[500010];
17 int n;
18 int sta[500010],top=0;
19 double inline Px(int a,int b){
20     return (l[a].B-l[b].B)/(l[b].A-l[a].A);
21 }
22 bool c[500010];
23 int main(){
24     scanf("%d",&n);
25     for(int i=1;i<=n;i++){
26         scanf("%lf%lf",&l[i].A,&l[i].B);
27         l[i].num=i;
28     }
29     sort(l+1,l+1+n);
30     sta[++top]=1;
31     for(int i=2;i<=n;i++){
32         if(!sign(l[i].A-l[sta[top]].A)) continue;
33         while(top>1&&sign(Px(i,sta[top-1])-Px(sta[top],sta[top-1]))<=0) top--;
34         sta[++top]=i;
35     }
36     for(int i=1;i<=top;i++) c[l[sta[i]].num]=true;
37     for(int i=1;i<=n;i++)
38         if(c[i])
39             printf("%d ",i);
40     return 0;
41 }

 

posted @ 2017-09-19 18:55  halfrot  阅读(128)  评论(0编辑  收藏  举报