2019杭电多校联赛第一场 D - Vacation (签到题)
话不多说先上题目
题意
汤姆面前有n辆车,每辆车的车长为s,车到红绿灯线的距离为l,车速为v。
这个道路很窄只能通过一辆车,所以当后面的车追上前面车的时候,后面车的车速只能和前面的车速一样。
求汤姆车头到达红绿灯线的时间。
多组输入
第一行输入n,代表汤姆前面有n辆车
第二行有n+1个数据,第一个数据是汤姆车辆的车长,后面n个是在他前面车辆的车长
第三行有n+1个数据,第一个数据是汤姆车辆到红绿灯线的距离,后面n个是在他前面车辆到红绿灯线的距离
第死行有n+1个数据,第一个数据是汤姆车辆的速度,后面n个是在他前面车辆的速度
思路
这个题目不能够暴力的去推导汤姆到达终点的时间。我们考虑到即使前面的车辆过了红绿灯还是会影响后面车的车速,所以我们可以假设红绿灯后面就是停车场,我们要让前面n辆车都停进去。
第一辆车到停车距离为:l1 + n辆车的车长
第二辆车到停车距离为:l2+ n辆车的车长 - 第一辆车的车长
第三辆车到停车距离为:l3+ n辆车的车长 - 第一辆车的车长 - 第二辆车的车长
以此类推
找出所有车到停车场需要的最长时间。就是汤姆到达红绿灯线的时间。
官方题解
把第 i 辆车追上第 i + 1 辆车当作一个事件,显然只有 n 个事件,且第 i 辆车追上第
i + 1 辆车只可能会对第 i − 1 辆车追上第 i 辆车的时间产生影响,且时间一定是变小,因此
可以维护车之间的距离和速度来计算事件发生时间,用堆来找出最早发生的事件,不停处理
直到 0 车通过停车线。复杂度为 O(n log n)。
上述做法比较麻烦,可以直接二分最终时间,然后从第一辆车开始递推求出每辆车的最
终位置。复杂度为 O(n log C),也可以过。
UPD 发现有很多大佬写了 O(n) 的做法,大概是这样:最终通过停止线的时候,一定是
一个车后面堵着剩余所有的车,那么影响时间的就只有最前面这辆车,所以对于每一辆车,
假设是它是和 0 车堵在一起的最靠前的一辆车,那么可以计算出一个值,所有的车的计算
值的最大值就是答案。
AC代码
#include<stdio.h>
struct CAR{
long long l,s,v;
}car[100010];
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
double mtime = 0;
long long sum =0;
for(int i=0;i<=n;i++)
{
scanf("%lld",&car[i].s);
sum += car[i].s;
}
sum -= car[0].s;
for(int i=0;i<=n;i++)
scanf("%lld",&car[i].l);
for(int i=0;i<=n;i++)
{
scanf("%lld",&car[i].v);
}
for(int i=n;i>=0;i--)
{
if( (sum+car[i].l)*1.0/car[i].v > mtime)
{
mtime = (sum+car[i].l)*1.0/car[i].v;
}
sum -= car[i].s;
}
printf("%.10lf\n",mtime);
}
return 0;
}