「NEERC2014」 Knockout Racing
题意
给 N(1≤N≤1000)N(1\le N\le 1000)N(1≤N≤1000) 辆在一条直线上跑的车,每辆车在区间 [Ai,Bi](0≤Ai,Bi≤109,Ai≠Bi)[A_i,B_i](0\le A_i,B_i\le 10^9,A_i\ne B_i)[Ai,Bi](0≤Ai,Bi≤109,Ai=Bi) 中行驶,可以把速度都看作一个单位速度。
然后给 M(1≤M≤1000)M(1\le M\le 1000)M(1≤M≤1000) 个询问,每个询问都有一组 Xi,Yi,Ti(1≤Xi,Yi,Ti≤109)X_i,Y_i,T_i(1\le X_i,Y_i,T_i\le 10^9)Xi,Yi,Ti(1≤Xi,Yi,Ti≤109) ,表示问在 TiT_iTi 时,区间 [Xi,Yi][X_i,Y_i][Xi,Yi] 内有几辆车。
分析
我们注意到,题目里的 NNN 和 MMM 都不大,所以 O(NM)O(NM)O(NM) 的算法也可以过。
所以我们可以在每一组询问时,都直接暴力求解每辆车的位置,然后统计一遍就可以了。
经过观察,可以发现:因为车是来回往返的,时间为 TjT_jTj ,单次距离为 Bi−AiB_i-A_iBi−Ai ,所以当 Tj mod (Bi−Ai)T_j\bmod (B_i-A_i)Tjmod(Bi−Ai) 为偶数时,是从 AiA_iAi 往 BiB_iBi,此时该车距离 AiA_iAi 点为 Tj mod (Bi−Ai)T_j\bmod (B_i-A_i)Tjmod(Bi−Ai) ;为奇数时,是从 BiB_iBi 往 AiA_iAi ,此时该车距离 AiA_iAi 点为 Tj−Tj mod (Bi−Ai)T_j-T_j\bmod (B_i-A_i)Tj−Tjmod(Bi−Ai) 。
我们此时求的距离是到 AiA_iAi 的,而不是真实的位置,所以还要再加上 AiA_iAi 。
Code
#include<bits/stdc++.h>
typedef long long ll;//个人习惯,没必要加long long
char buf[1<<21],*p1=buf,*p2=buf,obuf[1<<21],*O=obuf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
using namespace std;
inline ll read(){ll x=0,f=1;char c=getchar();while(c<48||c>57){if(c==45)f=0;c=getchar();}while(c>47&&c<58)x=(x<<3)+(x<<1)+(c^48),c=getchar();return f?x:-x;}
ll n,m,x,y,t,space[1005],ans;
struct car{
ll a,b;
}c[1005];//每辆车
signed main(){
n=read(),m=read();
for(int i=0;i<n;++i){
c[i].a=read(),c[i].b=read();
}//输入A,B
for(int j=0;j<m;++j){
x=read(),y=read(),t=read(),ans=0;
memset(space,0,sizeof space);
for(int i=0;i<n;++i){
if((t/(c[i].b-c[i].a))%2==1){
space[i]=(c[i].b-c[i].a)-t%(c[i].b-c[i].a);
}
else{
space[i]=t%(c[i].b-c[i].a);
}
space[i]+=c[i].a;//求车的位置,记住要在c[i].a的基础上加
if(space[i]>=x&&space[i]<=y)++ans;//统计
}
printf("%lld\n",ans);//输出
}
return 0;
}
文章描述了解决一个比赛问题的方法,涉及N辆在区间[Ai,Bi]内来回行驶的车辆,对于M个查询,计算在特定时间T下某个区间内车辆的数量。通过分析车辆的移动规律,提出O(NM)的算法并给出C++代码实现。

333

被折叠的 条评论
为什么被折叠?



