CodeForces 989D

题意略。

思路:

可以看成是所有的云彩照常运动,而月亮在跑。只要两个云彩相交后,在分离前月亮能赶到,就算是符合题意的。

可以知道,两个相隔越远的相向运动地云彩是越有可能符合题意的,因为它们相遇所用时间更长,这样月亮越有可能赶到。

假设云彩1为(l1,r1) ,云彩2为(l2,r2) ,r1 < l2 ,且两个云彩相向运动,云彩长度为 l 。我们令中心点p = (r1 + l2) / 2。

月亮赶到p点所需时间为runtime = p / wmax,两个云彩在相交后相离所用时间为 time = abs(r1 - l2) + l。

只要runtime < time,那么就合法。

我们现在只需要明白一个事实,在数轴上向右运动的云彩中,假设云彩1比云彩2靠左,那么云彩1对答案的贡献值中,必然还包括了云彩2对答案的贡献值。

基于以上性质,我们可以对两种方向运动的云彩分别进行排序,再用双指针。这样后面的解,就可以利用上前面计算出的值。

详见代码:

#include<bits/stdc++.h>
#define maxn 100005
using namespace std;
typedef long long LL;

double store1[maxn],store2[maxn];
int tail1,tail2,n;
double l,wmax;

int main(){
    scanf("%d%lf%lf",&n,&l,&wmax);
    double x,v;
    for(int i = 0;i < n;++i){
        scanf("%lf%lf",&x,&v);
        if(v == 1.0) store1[tail1++] = x;
        else store2[tail2++] = x;
    }
    //printf("tail1 == %d tail2 == %d\n",tail1,tail2);
    sort(store1,store1 + tail1);
    sort(store2,store2 + tail2);
    LL ans = 0;
    LL cur = 0;
    for(int i = tail1 - 1,j = tail2 - 1;i >= 0;--i){
        for(;j >= 0;--j){
            double l1 = store1[i],r1 = l1 + l;
            double l2 = store2[j],r2 = l2 + l;
            if(l1 > l2) break;
            double midtime = fabs(r1 - l2) / 2 + l;
            double mid = (r1 + l2) / 2;
            double time = fabs(mid) / wmax;
//            printf("time == %lf midtime == %lf\n",time,midtime);
//            printf("(1:%d,2:%d) is %s\n",i,j,time < midtime ? "OK" : "NO");
            if(time < midtime) ++cur;
            else break;
        }
        ans += cur;
    }
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/tiberius/p/9255056.html