题目:http://acm.hdu.edu.cn/showproblem.php?pid=6136
题意:在一个环上有n个人,每个人在不同的初始位置以及有不同的速度,每个人的武器强度为i,当相遇时武器强度弱的死亡,问比赛结束时的时间
看了题解还是写了很久 开始自己维护的太复杂 实际上只需要维护左右是谁就行了
官方题解 :
解法一
第一种解法比较直观,最初始状态环上有 nnn 个人,第一次淘汰发生必然是环上相邻的两个人相撞。注意到第一个被淘汰的人不会对后续过程有任何影响,如果我们能找出谁是第一个被淘汰的,直接把这个人从初始状态中删除,就能把问题变成一个只有 n−1n-1n−1 个人的子问题,这个子问题和原问题有相同的答案。
于是我们可以用一个堆维护环上所有相邻人相遇的时间,从中取出最小值,就能找到第一个被淘汰的人,这个人删除后,原本不相邻的两个人就相邻了,同样求出他们的相遇时间,加入堆中,重复执行这一过程,直到找到最后一个被淘汰的人为止。算法复杂度 O(nlogn)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define lson i<<1
#define rson i<<1|1
using namespace std;
const int N=2e5+5;
int d[N],v[N],l[N],r[N];
bool use[N];
int n,len;
struct people
{
int d,v,num;
bool operator <(const people&tem) const
{
return d<tem.d;
}
}a[N];
struct p
{
int x,y;
double t;
p(int xx=0,int yy=0)
{
x=xx;y=yy;
if (x>y)
{
if (a[x].v>a[y].v)
t=(len-abs(a[y].d-a[x].d))*1.0/(abs(a[y].v-a[x].v)*1.0);
else t=abs(a[y].d-a[x].d)*1.0/(abs(a[y].v-a[x].v)*1.0);
}
else
{
if (a[y].v>a[x].v)
t=(len-abs(a[y].d-a[x].d))*1.0/(abs(a[y].v-a[x].v)*1.0);
else t=abs(a[y].d-a[x].d)*1.0/(abs(a[y].v-a[x].v)*1.0);
}
}
bool operator <(const p&tem) const
{
return t>tem.t;
}
};
int gcd(int x,int y)
{
if (x<y) swap(x,y);
int t;
while(y)
{
t=x%y;
x=y;
y=t;
}
return x;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&len);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i].d);
a[i].num=i;
}
for(int i=1;i<=n;i++)
scanf("%d",&a[i].v);
sort(a+1,a+1+n);
priority_queue<p> que;
for(int i=1;i<=n;i++)
{
que.push(p(i,i+1>n?1:i+1));
l[i]=i-1<1?n:i-1;
r[i]=i+1>n?1:i+1;
}
memset(use,0,sizeof(use));
int sz=n-1;
int x,y;
while(!que.empty())
{
p t=que.top();que.pop();
if (use[t.x]||use[t.y]) continue;
if (a[t.x].num<a[t.y].num)
{
use[t.x]=1;
l[t.y]=l[t.x];r[l[t.x]]=t.y;
que.push(p(l[t.x],t.y));
}
else
{
use[t.y]=1;
r[t.x]=r[t.y];l[r[t.y]]=t.x;
que.push(p(t.x,r[t.y]));
}
sz--;
if (sz==0)
{
x=t.x;y=t.y;
break;
}
}
int t1=abs(a[x].d-a[y].d);
int t2=abs(a[x].v-a[y].v);
if ((x>y&&a[x].v>a[y].v)||(x<y&&a[y].v>a[x].v))
t1=len-t1;
int tt=gcd(t1,t2);
t1/=tt;t2/=tt;
printf("%d/%d\n",t1,t2);
}
return 0;
}