Description
一个周长为L的圆上有
Input
第一行一整数
Output
输出只剩一个点的时刻,结果输出最简分数
Sample Input
2
2 4
0 2
3 2
10 100
56 89 62 71 7 24 83 1 47 52
9 -16 34 -38 47 49 -32 17 39 -9
Sample Output
2/1
37/7
Solution
由于速度不同,故最后必然只剩下一个点,维护相邻两点相遇用时,每次选出时间最短的两个点必然是最先碰撞的,把能量值小的删掉后这个点前后的点变成一对相邻点,把这对点的相遇时间求出来接着和其他时间比较,用链表维护点的前后关系,用优先队列维护相遇时间,时间复杂度O(nlogn)
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
#define maxn 100005
struct Point
{
int w,d,v;
bool operator<(const Point &b)const
{
return d<b.d;
}
}p[maxn];
struct node
{
int u,v,x,y,w;
bool operator<(const node &b)const
{
return 1ll*x*b.y>1ll*b.x*y;
};
};
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
priority_queue<node>que;
int T,n,L,Pre[maxn],Next[maxn],vis[maxn];
void get(int i,int j,int &x,int &y)
{
int di=p[i].d,vi=p[i].v;
int dj=p[j].d,vj=p[j].v;
if(vi<vj)swap(di,dj),swap(vi,vj);
y=vi-vj;
if(di<dj)x=dj-di;
else x=L+dj-di;
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&L);
for(int i=0;i<n;i++)scanf("%d",&p[i].d);
for(int i=0;i<n;i++)scanf("%d",&p[i].v);
for(int i=0;i<n;i++)p[i].w=i;
sort(p,p+n);
int x,y,g;
while(!que.empty())que.pop();
for(int i=0;i<n;i++)
{
vis[i]=0,Pre[i]=(i-1+n)%n,Next[i]=(i+1)%n;
get(i,Next[i],x,y);
que.push((node){i,Next[i],x,y});
}
node a;
for(int k=1;k<n;k++)
{
int i,j;
while(1)
{
a=que.top(),que.pop();
i=a.u,j=a.v;
if(!vis[i]&&!vis[j])break;
}
if(k==n-1)
{
get(i,j,x,y);
g=gcd(x,y);
printf("%d/%d\n",x/g,y/g);
break;
}
if(p[i].w<p[j].w)
{
vis[i]=1;
get(Pre[i],j,x,y);
que.push((node){Pre[i],j,x,y});
Next[Pre[i]]=j,Pre[j]=Pre[i];
}
else
{
vis[j]=1;
get(i,Next[j],x,y);
que.push((node){i,Next[j],x,y});
Next[i]=Next[j],Pre[Next[j]]=i;
}
}
}
return 0;
}

解决一个数学问题,涉及多个点在一个圆形路径上以不同速度移动并相互碰撞的情况。使用优先队列和链表来高效地预测和处理碰撞事件。
&spm=1001.2101.3001.5002&articleId=78094804&d=1&t=3&u=45522c94d8c6453b9bc5d8f663daf14c)
1037

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



