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

时间:2022-03-12 18:13:00

题目传送: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)分到凸包上的点的斜率。维护最小值。

 #include<bits/stdc++.h>
using namespace std;
const double eps=1e-;
const double inf=1e20;
const int maxn=1e5+;
int sgn(double x){
if (fabs(x)<eps) return ;
if (x<) return -;
return ;
}
struct point{
double x,y;
int id; double ans;
point(){}
point(double _x,double _y):x(_x),y(_y){}
point operator +(const point &b)const{
return point(x+b.x,y+b.y);
}
point operator -(const point &b)const{
return point(x-b.x,y-b.y);
}
double operator ^(const point &b)const{
return x*b.y-y*b.x;
}
bool operator <(const point &b)const{
if (sgn(x-b.x)==) return y<b.y;
return x<b.x;
}
}; point p[maxn],pp[maxn];
int n,m;
double calc(point a,point b){
if (sgn(a.x-b.x)==) return 1.0;
return (a.y-b.y)/(a.x-b.x);
}
double cross(point p,point a,point b){
return (a-p)^(b-p);
}
void convex_hull(point p[],int N,point q[]){
sort(p,p+N);
int m=;
for (int i=;i<N;i++){
if (p[i].id>n){
if (m==) continue;
int l=,r=m-,mid;
while (l<r){
mid=(l+r)>>;
if (calc(p[i],q[mid])<calc(p[i],q[mid+])){
l=mid;
}
else r=mid-;
}
p[i].ans=min(p[i].ans,calc(p[i],q[l]));
}
else{
while (m> && cross(q[m-],q[m-],p[i])<=) m--;
q[m++]=p[i];
}
}
int k=m;
for (int i=N-;i>=;i--){
if (p[i].id>n){
if (m==k) continue;
int l=,r=m-,mid;
while (l<r){
mid=(l+r)>>;
if (calc(p[i],q[mid])<calc(p[i],q[mid+])){
l=mid;
}
else r=mid-;
}
p[i].ans=min(p[i].ans,calc(p[i],q[l]));
}
else{
while (m>k && cross(q[m-],q[m-],p[i])<=) m--;
q[m++]=p[i];
}
}
}
bool cmp(point a,point b){
return a.id<b.id;
}
int main(){
cin >> n;
for (int i=;i<n;i++){
cin >> p[i].x >> p[i].y;
p[i].id=i+; p[i].ans=inf;
}
cin >> m;
for (int i=n;i<n+m;i++){
cin >> p[i].x >> p[i].y;
p[i].id=i+; p[i].ans=inf;
}
convex_hull(p,n+m,pp);
for (int i=;i<n+m;i++){p[i].x*=-; p[i].y*=-;}
convex_hull(p,n+m,pp);
sort(p,p+n+m,cmp);
for (int i=n;i<n+m;i++)
if (p[i].ans>=) cout << "No cross\n";
else printf("%.7f\n",-p[i].ans);
return ;
}