链接:https://www.nowcoder.com/acm/contest/140/C
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
Special Judge, 64bit IO Format: %lld
题目描述
There is an infinite plane. White Cloud has n lines which are not parallel to the Oy axis. These lines in the plane are in the form y=ax+b.
White Rabbit will have a trip in the plane. It will start at time 0 and go straight along a line. specifically, White Rabbit uses 2 parameters C and D,denoting that at time x, White Rabbit is at the position(x,C*x+D).
If at some time, White Rabbit is located at one of White Cloud’s lines, White Cloud will receive a message immediately.
White Rabbit has m pairs (C[i],D[i]) for i=1..m. For each i=1..m, White Cloud wants to know if White Rabbit uses (C[i],D[i]) , when is the last time White Cloud can receive a message.
输入描述:
The first line of input contains an integer n. (n<=50000)
For the next n lines, the i-th line contains 2 integers A[i], B[i], describing the i-th line. (-1e9<=A[i],B[i]<=1e9)
All numbers A[i] are different.
The next line contains an integer m. (m<=50000)
For the next m lines, the i-th line contains 2 integers C[i],D[i], describing the i-th pair.(-2e9<=C[i],D[i]<=2e9)
Each C[j] is different from any of the numbers A[i].
Each D[j] is different from any of the numbers B[i].
输出描述:
Print m lines. The i-th line contains a real number with at least 6 digits after the decimal point, denoting the latest time White Cloud can receive a message. Your answer must be correct within an absolute error of 1e-6.
If White Cloud can’t receive any message during White Rabbit’s trip,print a string “No cross”.
示例1
输入
2
0 -1
1 2
3
-1 4
2 -2
2 5
输出
5.000000000000000
4.000000000000000
No cross
题解:一条直线的表达式为
ax+b
a
x
+
b
,一次询问线的表达式为
cx+d
c
x
+
d
,则这两条线的交点是
x=−b−da−c
x
=
−
b
−
d
a
−
c
。
如果我们把它们看做两个点
(a,b)(c,d)
(
a
,
b
)
(
c
,
d
)
,则直线交点就是现在这两个点的斜率的相反数。
问题就转化成了:平面上有若干个点,每次给一个点,问这个点到平面上所有点的斜率最小值。
这个就可以用凸包进行维护了。
因为要保证斜率最小,所以凸包里维护的并不是最外面的点,而是里面的点。
更新答案的时候,利用二分在凸包里查找。
#include<bits/stdc++.h>
using namespace std;
const int MAX=1e5+5;
typedef long long ll;
struct Point
{
ll x,y,id;
Point(ll x=0,ll y=0):x(x),y(y){}
void show(){cout<<"("<<x<<","<<y<<")"<<endl;}
}p[MAX],ch[MAX];
Point operator-(Point A,Point B){return (Point){A.x-B.x,A.y-B.y};} //向量A-B
ll cross(Point A,Point B){return A.x*B.y-A.y*B.x;} //向量A B的叉积
double ans[MAX];
double f(Point A){return -1.0*A.y/A.x;}
int cmp(const Point& x,const Point& y)
{
if(x.x==y.x)return x.y<y.y;
return x.x<y.x;
}
int Tu(Point *p,int n,Point *ch) //求凸包
{
sort(p,p+n,cmp);
int m=0;
for(int i=0;i<n;i++)
{
if(p[i].id)
{
int l=0,r=m-1;
while(r>=l)
{
int mid=(l+r)/2;
if(cross(ch[mid]-p[i],ch[mid+1]-p[i])>0)r=mid-1;
else l=mid+1;
}
for(int j=l-4;j<=r+4;j++)if(0<=j&&j<m)ans[p[i].id]=max(ans[p[i].id],f(p[i]-ch[j]));
continue;
}
while(m>1&&cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])>0)m--;
ch[m++]=p[i];
}
m=0;
for(int i=n-1;i>=0;i--)
{
if(p[i].id)
{
int l=0,r=m-1;
while(r>=l)
{
int mid=(l+r)/2;
if(cross(ch[mid]-p[i],ch[mid+1]-p[i])>0)r=mid-1;
else l=mid+1;
}
for(int j=l-4;j<=r+4;j++)if(0<=j&&j<m)ans[p[i].id]=max(ans[p[i].id],f(p[i]-ch[j]));
continue;
}
while(m>1&&cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])>0)m--;
ch[m++]=p[i];
}
if(n>1)m--;
return m;
}
int main()
{
int n;cin>>n;
for(int i=0;i<n;i++)scanf("%lld%lld",&p[i].x,&p[i].y),p[i].id=0;
int m;cin>>m;
for(int i=n;i<n+m;i++)scanf("%lld%lld",&p[i].x,&p[i].y),p[i].id=i-n+1;
Tu(p,n+m,ch);
for(int i=1;i<=m;i++)
{
if(ans[i]==0)puts("No cross");
else printf("%.15lf\n",ans[i]);
}
return 0;
}