Description
数轴上有n个等质量小球,每个小球有一个初速度vi和一个运动方向,运动过程小球的加速度和速度乘积是常数c,两小球碰撞看作完全弹性碰撞,q次查询,每次查询t s后速度第k大的小球速度
Input
第一行一整数T表示用例组数,每组用例首先输入两个整数n和c表示小球数量以及小球运动过程中加速度和速度的乘积,之后n行每行三个整数xi,vi,di表示该小球的初始位置、初速度以及初始运动方向(-1向左1向右),然后输入一整数q表示查询数,最后q行每行两个整数t和k表示查询t s后速度第k大的小球速度
(n,q<=10^5,c<=10^9,1<=vi<=10^5,1<=xi<=10^9,t<=10^9,1<=k<=n)
Output
对于每次查询,输出t s后速度第k大的小球速度,结果保留到小数点后三位
Sample Input
1
3 7
3 3 1
3 10 -1
2 7 1
3
2 3
1 2
3 3
Sample Output
6.083
4.796
7.141
Solution
高中物理题,由于小球质量均相同且碰撞是完全弹性碰撞,故碰撞只是交换速度,而查询只是查询第k大的速度,故此处完全不用考虑碰撞,将碰撞的两小球看作互相“穿过”即可,对于初速度为v0的小球,下面来求其t s后的速度
由结果看出v0越大v越大,故首先对v0排序,之后对于每次查询,由上述公式算出第k个小球的速度即为答案
Code
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
#define maxn 111111
int T,n,c,q,v[maxn],x,d;
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&c);
for(int i=1;i<=n;i++)scanf("%d%d%d",&v[i],&x,&d);
sort(v+1,v+n+1);
scanf("%d",&q);
while(q--)
{
int t,k;
scanf("%d%d",&t,&k);
double ans=sqrt(2.0*c*t+1.0*v[k]*v[k]);
printf("%.3f\n",ans);
}
}
return 0;
}