【推导】Codeforces Round #478 (Div. 2) D. Ghosts

时间:2023-03-09 16:30:10
【推导】Codeforces Round #478 (Div. 2) D. Ghosts

题意:给你一条直线以及初始时刻这条直线上的一些人的坐标,以及他们的速度矢量。让你对每个人计算他在过去无限远到将来无限远的时间内会与多少人处于同一个点,然后对每个人的这个值求和。

列方程组:两个人i,j相撞的条件是:

a*x(i)+b+t*vy(i)=a*xj+b+t*vy(j)

x(i)+t*vx(i)=xj+t*vx(j)

化简得vy(i)-a*vx(i)=vy(j)-a*vx(j),对这个值排序,就能统计了。别忘了减去vx相等的点对贡献的答案(这种情况画个图出来,显然永远不会相撞)。

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
int n;
ll a,b;
typedef pair<ll,ll> Point;
Point c[200005];
int main(){
ll x,va,vb;
scanf("%d%I64d%I64d",&n,&a,&b);
for(int i=1;i<=n;++i){
scanf("%I64d%I64d%I64d",&x,&va,&vb);
c[i].first=vb-a*va;
c[i].second=va;
}
sort(c+1,c+n+1);
ll ans=0;
int sta;
for(int i=1;i<=n;++i){
if(i==1 || c[i].first!=c[i-1].first){
sta=i;
}
if(i==n || c[i].first!=c[i+1].first){
ans+=(ll)(i-sta+1)*(ll)(i-sta);
}
}
for(int i=1;i<=n;++i){
if(i==1 || (c[i].first!=c[i-1].first || c[i].second!=c[i-1].second)){
sta=i;
}
if(i==n || (c[i].first!=c[i+1].first || c[i].second!=c[i+1].second)){
ans-=(ll)(i-sta+1)*(ll)(i-sta);
}
}
printf("%I64d\n",ans);
return 0;
}