题意略。
思路:
可以看成是所有的云彩照常运动,而月亮在跑。只要两个云彩相交后,在分离前月亮能赶到,就算是符合题意的。
可以知道,两个相隔越远的相向运动地云彩是越有可能符合题意的,因为它们相遇所用时间更长,这样月亮越有可能赶到。
假设云彩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 ",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 ",time,midtime); // printf("(1:%d,2:%d) is %s ",i,j,time < midtime ? "OK" : "NO"); if(time < midtime) ++cur; else break; } ans += cur; } printf("%lld ",ans); return 0; }