Description
炮艇大赛是一项危险的比赛。为了赢得这场比赛,参赛者可能会牺牲自己的生命。
参赛者将会在一条长度为 L L L的环形轨道上比赛。在比赛开始时( 0 0 0时刻),所有参赛者站在轨道不同的位置上,其中第 i i i 名参赛者站在位置 d i ( 0 ≤ d i < L ) d_i(0≤d_i<L) di(0≤di<L) 上。然后比赛开始。每位参赛者驾驶着它的炮艇,速度为 v i v_i vi (速度可以为正,可以为负,也可以为 0 0 0。速度为正表示参赛者顺时针移动,速度为负表示参赛者逆时针移动)。每位参赛者的速度都不同。
第 i i i 名参赛者有 i i i 点能量值。在比赛过程中,参赛者们可能会相遇(此处相遇指的是参赛者们在同一时刻恰好落在同一地点)。每两位参赛者 i , j i,j i,j 相遇时,能量值低的参赛者将被击毙出局。
当赛场上只剩下一个人时,比赛结束。
问比赛什么时候结束。
Input
第一行包含两个正整数 n , L ( 1 ≤ n ≤ 1 0 5 , 1 ≤ L ≤ 1 0 9 ) n,L(1≤n≤10^5,1≤L≤10^9) n,L(1≤n≤105,1≤L≤109)
接下来一行包含 n 个不同的整数 d i ( 0 ≤ d i < L ) d_i(0≤d_i<L) di(0≤di<L)
接下来一行包含 n 个不同的整数 v i ( ∣ v i ∣ ≤ 1 0 9 ) v_i(|v_i|≤10^9) vi(∣vi∣≤109)
Output
输出一个分数 X / Y X/Y X/Y 表示结束时刻,其中 g c d ( X , Y ) = 1 gcd(X,Y)=1 gcd(X,Y)=1 。若答案为 0 0 0,应只输出“0”(不含引号)。
题解:
用堆模拟就好。
先算出所有相邻两个人相遇的时间,丢进堆里,每次取出时间最小的一对人,移出其中一个,添加新的相邻两个人相遇的时间入堆即可。最后堆中剩下的一对人的相遇时间就是答案。
代码:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
typedef long long ll;
using namespace std;
const int N=100005;
int n,m,right[N],left[N];
ll l;
bool out[N];
ll gcd(ll x,ll y){
return y?gcd(y,x%y):x;
}
struct data{
ll d,v;
int id;
bool operator < (const data &n) const{
return d<n.d;
}
}a[N],b[N];
struct num{
ll a,b;
int x,y;
num(){x=0;y=1;}
num(ll aa,ll bb,int xx,int yy){a=aa;b=bb;x=xx;y=yy;}
bool operator < (const num &n) const{
return a*n.b>b*n.a;
}
};
priority_queue<num> pq;
ll get(ll xl,ll xr,bool f){
if(f){
if(xr<xl){
return xl-xr;
}else{
return xl+l-xr;
}
}else{
if(xr>xl){
return xr-xl;
}else{
return xr+l-xl;
}
}
}
num calc(ll s,ll v,int x,int y){
return (num){s,v,x,y};
}
int main(){
scanf("%d%lld",&n,&l);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i].d);
a[i].id=i;
left[i]=i-1;
right[i]=i+1;
}
left[1]=n;
right[n]=1;
for(int i=1;i<=n;i++){
scanf("%lld",&a[i].v);
}
sort(a+1,a+n+1);
for(int i=1;i<=(n==2?1:n);i++){
int j=i+1;
if(j>n){
j=1;
}
bool f1=a[i].v<0,f2=a[j].v<0;
int s,t;
if(abs(a[i].v)>abs(a[j].v)){
s=a[i].d;
t=a[j].d;
}else{
s=a[j].d;
t=a[i].d;
}
if(f1==f2){
pq.push(calc(get(s,t,f1),abs(a[i].v-a[j].v),i,j));
}else{
pq.push(calc(get(a[i].d,a[j].d,f1),abs(a[i].v)+abs(a[j].v),i,j));
}
}
while(pq.size()>1){
num now=pq.top();
pq.pop();
if(out[now.x]||out[now.y]){
continue;
}
if(a[now.x].id>a[now.y].id){
swap(now.x,now.y);
}
out[now.x]=1;
int ll=left[now.x],rr=right[now.x];
if(ll==rr){
break;
}
right[ll]=rr;
left[rr]=ll;
bool f1=a[ll].v<0,f2=a[rr].v<0;
int s,t;
if(abs(a[ll].v)>abs(a[rr].v)){
s=a[ll].d;
t=a[rr].d;
}else{
s=a[rr].d;
t=a[ll].d;
}
if(f1==f2){
pq.push(calc(get(s,t,f1),abs(a[ll].v-a[rr].v),ll,rr));
}else{
pq.push(calc(get(a[ll].d,a[rr].d,f1),abs(a[ll].v)+abs(a[rr].v),ll,rr));
}
}
num res=pq.top();
ll g=gcd(res.a,res.b);
res.a/=g;
res.b/=g;
printf("%lld/%lld\n",res.a,res.b);
return 0;
}