目录
链接:https://www.nowcoder.com/acm/contest/140/C
来源:牛客网
题目描述
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".
题意:
大概就是已知n条直线y=a[i]x+b[i],有m次询问,每次给出一条线段y=c[i]x+d[i],问是否有x>0的交点,如果有输出横坐标。
思路:
这个题比较巧妙,线段的斜率和截距转换成了两点之间的斜率,然后用凸包求解。
解法:
通过和
联立,可以解得
,这个题的巧妙之处就在这里,x不正好是点
和点
连线斜率的相反数吗。将之前输入的所有直线的斜率和截距看成点,然后通过凸包就可以解出最大值了。
AC代码:
#include <bits/stdc++.h>
using namespace std;
const int mod = 1000000007;
const int N =4e5 + 7;
const double ex = 1e-8;
typedef unsigned long long ull;
typedef long long ll;
typedef double dl;
struct Point{
double x,y;
int id;
}p[N],u[N];
double ans[N];
int n,m;
bool cmp(Point a,Point b)
{
if(a.x == b.x) return a.y < b.y;
return a.x < b.x;
}
inline double cal(Point a,Point b)
{
return (b.y - a.y) / (a.x - b.x);
}
void binary_find()
{
int t = 0;
for(int i = 0;i < m + n;++i){
if(p[i].id){
int l = 1,r = t,mid1,mid2;
if(!t || p[i].y > u[1].y) continue;
while(r - l > 2){
mid1 = (l * 2 + r) / 3;
mid2 = (l + 2 * r) / 3;
if(cal(u[mid1],p[i]) > cal(u[mid2],p[i])) r = mid2;
else l = mid1;
}
for(int j = l;j <= r;++j)
ans[p[i].id]=max(ans[p[i].id],cal(u[j],p[i]));
}
else{
while(t > 0 && p[i].y > u[t].y) t--;
while(t > 1 && cal(u[t],p[i]) < cal(u[t - 1],p[i])) t--;
if(t == 1 && p[i].y > u[t].y){
u[t].x = p[i].x;
u[t].y = p[i].y;
}
else{
u[++t].x = p[i].x;
u[t].y = p[i].y;
}
}
}
}
int main()
{
scanf("%d",&n);
for(int i = 0;i < n;++i)
scanf("%lf%lf",&p[i].x,&p[i].y);
scanf("%d",&m);
for(int i = 0;i < m;++i){
scanf("%lf%lf",&p[i + n].x,&p[i + n].y);
p[i + n].id = i + 1;
}
sort(p,p + n + m,cmp);
for(int i = 1;i <= m;++i) ans[i] = -1.0;
binary_find();
for(int i = 0;i < n + m;++i){
p[i].x *= -1;
p[i].y *= -1;
}
reverse(p,p + n + m);
binary_find();
for(int i = 1;i <= m;++i){
if(ans[i] < 0) printf("No cross\n");
else printf("%.10lf\n",ans[i]);
}
return 0;
}