炮艇大赛之正式赛
题目
Description
炮艇大赛是一项危险的比赛。为了赢得这场比赛,参赛者可能会牺牲自己的生命。
参赛者将会在一条长度为\(L\)的环形轨道上比赛。在比赛开始时(\(0\)时刻),所有参赛者站在轨道不同的位置上,其中第 i 名参赛者站在位置 \(di(0≤di<L)\) 上。然后比赛开始。每位参赛者驾驶着它的炮艇,速度为 \(vi\) (速度可以为正,可以为负,也可以为\(0\)。速度为正表示参赛者顺时针移动,速度为负表示参赛者逆时针移动)。每位参赛者的速度都不同。
第 \(i\) 名参赛者有 \(i\) 点能量值。在比赛过程中,参赛者们可能会相遇(此处相遇指的是参赛者们在同一时刻恰好落在同一地点)。每两位参赛者 \(i,j\) 相遇时,能量值低的参赛者将被击毙出局。
当赛场上只剩下一个人时,比赛结束。
问比赛什么时候结束。
Input
第一行包含两个正整数 \(n,L(1\leq n \leq 10^5,1\leq L\leq 10^9)\)
接下来一行包含 n 个不同的整数 \(di(0\leq di < L)\)
接下来一行包含 n 个不同的整数 $vi(|vi| \leq109) $
Output
输出一个分数 \(X/Y\) 表示结束时刻,其中 \(gcd(X,Y)=1\) 。若答案为\(0\),应只输出“\(0\)”(不含引号)。
题解
直接模拟。
先排序。
显然最先相遇的一定相邻的。
于是我们把相邻的炮艇的相遇时间扔进小根堆。然后取出堆顶, 将被打败的删掉, 然后将新产生的相邻的炮艇的相遇时间扔进小根堆(这里可以用链表模拟炮艇序列)。 重复这个过程, 直到只剩一艘快艇。
代码
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
typedef long long LL;
typedef pair <LL, LL> pr;
inline LL gcd(LL a, LL b) { return !b ? a : gcd(b, a % b); }
const int N = 1e5 + 10;
struct Data
{
int x, y; double t;
Data() { }
Data(int _1, int _2, double _3) : x(_1), y(_2), t(_3) { }
inline bool operator < (Data rhs) const { return t > rhs.t; }
};
priority_queue <Data> q;
int n; LL L;
struct Info
{
LL d, v; int w, pre, nxt;
Info() { }
Info(LL _1, LL _2, int _3, int _4, int _5) : d(_1), v(_2), w(_3), pre(_4), nxt(_5) { }
} a[N];
pr calc(int x, int y)
{
if (a[x].v >= a[y].v) return make_pair((a[y].d - a[x].d + L) % L, a[x].v - a[y].v);
return make_pair(L - ((a[y].d - a[x].d + L) % L), a[y].v - a[x].v);
}
bool tag[N];
int main()
{
scanf("%d %lld", &n, &L);
if (n <= 1) return 0 & puts("0");
for (int i = 1; i <= n; i++)
scanf("%lld", &a[i].d);
for (int i = 1; i <= n; i++)
scanf("%lld", &a[i].v), a[i].w = i;
sort(a + 1, a + 1 + n, [](Info a, Info b) { return a.d < b.d; });
a[1].pre = n; a[1].nxt = 2;
a[n].pre = n - 1; a[n].nxt = 1;
for (int i = 2; i < n; i++)
a[i].pre = i - 1, a[i].nxt = i + 1;
for (int i = 1; i <= n; i++)
{
pr t = calc(i, a[i].nxt);
q.push( Data(i, a[i].nxt, (double) t.first / t.second) );
}
int cnt = 0;
Data tmp;
while (q.size() > 1)
{
tmp = q.top(); q.pop();
if (tag[tmp.x] || tag[tmp.y]) continue;
cnt++;
if (cnt == n-1) break;
if (a[tmp.x].w > a[tmp.y].w)
{
tag[tmp.y] = 1;
a[tmp.x].nxt = a[tmp.y].nxt;
a[a[tmp.x].nxt].pre = tmp.x;
pr t = calc(tmp.x, a[tmp.x].nxt);
q.push( Data(tmp.x, a[tmp.x].nxt, (double) t.first / t.second) );
}
else
{
tag[tmp.x] = 1;
a[tmp.y].pre = a[tmp.x].pre;
a[a[tmp.y].pre].nxt = tmp.y;
pr t = calc(a[tmp.y].pre, tmp.y);
q.push( Data(a[tmp.y].pre, tmp.y, (double) t.first / t.second) );
}
}
tmp = q.top();
pr t = calc(tmp.x, tmp.y);
printf("%lld/%lld\n", t.first / gcd(t.first, t.second), t.second / gcd(t.first, t.second));
return 0;
}