炮艇大赛之正式赛

题目

Description
炮艇大赛是一项危险的比赛。为了赢得这场比赛,参赛者可能会牺牲自己的生命。

参赛者将会在一条长度为(L)的环形轨道上比赛。在比赛开始时((0)时刻),所有参赛者站在轨道不同的位置上,其中第 i 名参赛者站在位置 (di(0≤di<L)) 上。然后比赛开始。每位参赛者驾驶着它的炮艇,速度为 (vi) (速度可以为正,可以为负,也可以为(0)。速度为正表示参赛者顺时针移动,速度为负表示参赛者逆时针移动)。每位参赛者的速度都不同。

(i) 名参赛者有 (i) 点能量值。在比赛过程中,参赛者们可能会相遇(此处相遇指的是参赛者们在同一时刻恰好落在同一地点)。每两位参赛者 (i,j) 相遇时,能量值低的参赛者将被击毙出局。

当赛场上只剩下一个人时,比赛结束。

问比赛什么时候结束。

Input
第一行包含两个正整数 (n,L(1leq n leq 10^5,1leq Lleq 10^9))

接下来一行包含 n 个不同的整数 (di(0leq 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
", t.first / gcd(t.first, t.second), t.second / gcd(t.first, t.second));
	
	return 0;
}
原文地址:https://www.cnblogs.com/2016gdgzoi509/p/11305273.html