[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 }