Codeforces Round #425 (Div. 2) C-Strange Radiation(二分答案)

C. Strange Radiation

    n people are standing on a coordinate axis in points with positive integer coordinates strictly less than 106. For each person we know in which direction (left or right) he is facing, and his maximum speed.
    You can put a bomb in some point with non-negative integer coordinate, and blow it up. At this moment all people will start running with their maximum speed in the direction they are facing. Also, two strange rays will start propagating from the bomb with speed s: one to the right, and one to the left. Of course, the speed s is strictly greater than people's maximum speed.
    The rays are strange because if at any moment the position and the direction of movement of some ray and some person coincide, then the speed of the person immediately increases by the speed of the ray.
    You need to place the bomb is such a point that the minimum time moment in which there is a person that has run through point 0, and there is a person that has run through point 10^6, is as small as possible. In other words, find the minimum time moment t such that there is a point you can place the bomb to so that at time moment t some person has run through 0, and some person has run through point 10^6.

Input

    The first line contains two integers n and s (2 ≤ n ≤ 10^5, 2 ≤ s ≤ 10^6) — the number of people and the rays' speed.

    The next n lines contain the description of people. The i-th of these lines contains three integers xi, vi and ti (0 < xi < 10^6, 1 ≤ vi < s, 1 ≤ ti ≤ 2) — the coordinate of the i-th person on the line, his maximum speed and the direction he will run to (1 is to the left, i.e. in the direction of coordinate decrease, 2 is to the right, i.e. in the direction of coordinate increase), respectively.

    It is guaranteed that the points 0 and 10^6 will be reached independently of the bomb's position.

Output

    Print the minimum time needed for both points 0 and 10^6 to be reached.

    Your answer is considered correct if its absolute or relative error doesn't exceed 10 - 6. Namely, if your answer is a, and the jury's answer is b, then your answer is accepted, if .

Examples

input
2 999
400000 1 2
500000 1 1
output
500000.000000000000000000000000000000

input
2 1000
400000 500 1
600000 500 2
output
400.000000000000000000000000000000

Note

    In the first example, it is optimal to place the bomb at a point with a coordinate of 400000. Then at time 0, the speed of the first person becomes 1000 and he reaches the point 106 at the time 600. The bomb will not affect on the second person, and he will reach the 0 point at the time 500000.

    In the second example, it is optimal to place the bomb at the point 500000. The rays will catch up with both people at the time 200. At this time moment, the first is at the point with a coordinate of 300000, and the second is at the point with a coordinate of 700000. Their speed will become 1500 and at the time 400 they will simultaneously run through points 0 and 10^6.

题目大意:

有一根0-10^6的数轴,上面有一些面朝左边或者右边的人,每个人都在一个整数位置,并且有一个固定的速度。
现在可以在数轴上任意一整数位置放一个炸弹,炸弹爆炸后,所有人同时以固定的速度向面朝的方向跑,同时炸弹爆炸处会出现一种奇怪的射线,以速度s同时向左边和右边传播,如果射线超过了一个人,这个人的速度会增加s,问炸弹放在哪里可以使得同时存在到达了0点和10^6点的人的时间最小,求最小时间。

此题比较简单,二分答案即可。
对时间二分,然后判断是否可行。
判断时,枚举每一个向左跑的人,算出为了使这个人在给定时间内到达0点,炸弹能放的位置集合,然后枚举每一个向右跑的人,同样算出到达10^6点的炸弹位置集合,把所有集合交起来,如果不为空就是可行。
注意到炸弹只能放在整数点,所以要注意取整。

代码:

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 1234567
using namespace std;
struct node{double x,v;};
node L[N],R[N];
int n,lcnt,rcnt;double s,EN=1000000;
bool ok(double t)
{
    int i,j,k;bool f=0;
    double tmp;
    int LL=1e6,RR=0;
    for(i=1;i<=lcnt;i++)
    {
        if(L[i].x==0||(L[i].v!=0&&L[i].x/L[i].v<=t)){f=1;LL=0;RR=EN;break;}
        if(L[i].x/(L[i].v+s)>t)continue;
        tmp=(t*(s*s-L[i].v*L[i].v)+L[i].v*L[i].x)/s;
        RR=max(RR,int(floor(tmp)));
        LL=min(LL,int(ceil(L[i].x)));
        f=1;
    }
    if(!f)return 0;
    for(i=1;i<=rcnt;i++)
    {
        if(R[i].x<LL&&(R[i].v!=0&&(EN-R[i].x)/R[i].v>t))continue;
        if(R[i].x==EN||(R[i].v!=0&&(EN-R[i].x)/R[i].v<=t))return 1;
        if((EN-R[i].x)/(R[i].v+s)>t)continue;
        if(RR>R[i].x&&LL<R[i].x)return 1;
        tmp=(R[i].x-RR)/(s-R[i].v);
        tmp=(EN-R[i].x-tmp*R[i].v)/(s+R[i].v)+tmp;
        if(tmp<=t)return 1;
    }
    return 0;
}
void EF(double l,double r)
{
    while(r-l>=0.0000000001)
    {
        double mid=(l+r)/2;
        if(ok(mid))r=mid;
        else l=mid;
    }
    printf("%.10lf",l);
}
int main()
{
    double x,y;int i,j,k;
    scanf("%d%lf",&n,&s);
    for(i=1;i<=n;i++)
    {
        scanf("%lf%lf%d",&x,&y,&k);
        if(k==1){++lcnt;L[lcnt].x=x;L[lcnt].v=y;}
        else{++rcnt;R[rcnt].x=x;R[rcnt].v=y;}
    }
    EF(0,1000000);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值