牛客第二场 C.message(计算几何+二分)

题目传送:https://www.nowcoder.com/acm/contest/140/C

题意:有n个云层,每个云层可以表示为y=ax+b。每个飞机的航线可以表示为时间x时,坐标为(x,cx+d)。问飞机旅程与最后一个云层相交的x坐标。不存在

分析:

可以确定两直线联立后解得交点x=(b-d)/(a-c)。

可以看做是点(a,b)和(c,d)的斜率的负数。

要求的最大的x,那么就变成了求得最小的斜率,答案最后再乘-1即可。

 

就是求每个(c,d)点到(a,b)的斜率,可以把每一个(a,b)看成一个点,求凸包。

每碰到一个(c,d)二(san)分到凸包上的点的斜率。维护最小值。

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const double eps=1e-8;
  4 const double inf=1e20;
  5 const int maxn=1e5+10;
  6 int sgn(double x){
  7     if (fabs(x)<eps) return 0;
  8     if (x<0) return -1;
  9     return 1;
 10 }
 11 struct point{
 12     double x,y;
 13     int id; double ans;
 14     point(){}
 15     point(double _x,double _y):x(_x),y(_y){}
 16     point operator +(const point &b)const{
 17         return point(x+b.x,y+b.y);
 18     } 
 19     point operator -(const point &b)const{
 20         return point(x-b.x,y-b.y);
 21     }
 22     double operator ^(const point &b)const{
 23         return x*b.y-y*b.x;
 24     }
 25     bool operator <(const point &b)const{
 26         if (sgn(x-b.x)==0) return y<b.y;
 27         return x<b.x;
 28     } 
 29 }; point p[maxn],pp[maxn]; 
 30 int n,m;
 31 double calc(point a,point b){
 32     if (sgn(a.x-b.x)==0) return 1.0;
 33     return (a.y-b.y)/(a.x-b.x);
 34 }
 35 double cross(point p,point a,point b){
 36     return (a-p)^(b-p);
 37 }
 38 void convex_hull(point p[],int N,point q[]){
 39     sort(p,p+N);
 40     int m=0;
 41     for (int i=0;i<N;i++){
 42         if (p[i].id>n){
 43             if (m==0) continue;
 44             int l=0,r=m-1,mid; 
 45             while (l<r){
 46                 mid=(l+r)>>1;
 47                 if (calc(p[i],q[mid])<calc(p[i],q[mid+1])){
 48                     l=mid;
 49                 }
 50                 else r=mid-1;
 51             }
 52             p[i].ans=min(p[i].ans,calc(p[i],q[l]));    
 53         }
 54         else{
 55             while (m>1 && cross(q[m-2],q[m-1],p[i])<=0) m--;
 56             q[m++]=p[i];
 57         }
 58     } 
 59     int k=m;
 60     for (int i=N-2;i>=0;i--){
 61         if (p[i].id>n){
 62             if (m==k) continue;
 63             int l=0,r=m-1,mid; 
 64             while (l<r){
 65                 mid=(l+r)>>1;
 66                 if (calc(p[i],q[mid])<calc(p[i],q[mid+1])){
 67                     l=mid;
 68                 }
 69                 else r=mid-1;
 70             }
 71             p[i].ans=min(p[i].ans,calc(p[i],q[l]));    
 72         }
 73         else{
 74             while (m>k && cross(q[m-2],q[m-1],p[i])<=0) m--;
 75             q[m++]=p[i];
 76         }
 77     } 
 78 }
 79 bool cmp(point a,point b){
 80     return a.id<b.id;
 81 }
 82 int main(){
 83     cin >> n;
 84     for (int i=0;i<n;i++){
 85         cin >> p[i].x >> p[i].y;
 86         p[i].id=i+1; p[i].ans=inf;
 87     }
 88     cin >> m;
 89     for (int i=n;i<n+m;i++){
 90         cin >> p[i].x >> p[i].y;
 91         p[i].id=i+1; p[i].ans=inf;
 92     }
 93     convex_hull(p,n+m,pp);
 94     for (int i=0;i<n+m;i++){p[i].x*=-1; p[i].y*=-1;}
 95     convex_hull(p,n+m,pp);
 96     sort(p,p+n+m,cmp);
 97     for (int i=n;i<n+m;i++)
 98         if (p[i].ans>=0) cout << "No cross
";
 99         else printf("%.7f
",-p[i].ans);
100     return 0;
101 } 
原文地址:https://www.cnblogs.com/changer-qyz/p/9826332.html