noip2017集训测试赛(六)Problem A: 炮艇大赛之正式赛

题目描述

给定一个长度为\(L \le 10^9\)的环形赛道, \(n \le 10^5\)个人在上面赛艇. 每个人的速度都不相同, 假如为正则顺时针走, 否则逆时针走. 当两个人相遇时, 他们就会开火, 编号小的那个人就会挂掉出局. 当只剩下一个人时, 这个人就获得胜利.

问: 多久以后游戏结束.

Solution

考虑什么时候游戏结束: 最后仅剩的两个人相遇, 则一个挂掉, 另一个胜利.

因此我们只要得到最后是哪两个人相遇即可.

考虑每次相遇的只能是位置相邻的两个人, 因此我们把相邻两个人相遇所需要的时间用一个堆维护起来, 每次找到最早相遇的两个人, 记录其中一个人挂掉, 并且将产生的新的相邻的两个人加入堆中即可.

#include <cstdio>
#include <cctype>
#include <algorithm>
#include <queue>
#include <cstring>
#include <cmath>

using namespace std;
namespace Zeonfai
{
	inline int getInt()
	{
		int a = 0, sgn = 1; char c;
		while (! isdigit(c = getchar())) if (c == '-') sgn *= -1;
		while (isdigit(c)) a = a * 10 + c - '0', c = getchar();
		return a * sgn;
	}
}
const int N = (int)1e5;
int n, L;
struct ting
{
	int d, v, w;
	inline int operator <(const ting &a) const { return d < a.d; }
}a[N + 7];
struct record
{
	int id[2];
	double T;
	inline record() {}
	inline record(int u, int v)
	{
		if (a[u].v > a[v].v) swap(u, v);
		T = (double)((a[u].d - a[v].d + L) % L) / (a[v].v - a[u].v);
		id[0] = u; id[1] = v;
		if (a[id[0]].w < a[id[1]].w) swap(id[0], id[1]);
	}
	inline int operator <(const record &a) const { return T > a.T; }
};
inline void getOutput(int a, int b)
{
	if (a == 0) { puts("0"); return; }
	int x = a, y = b; if (x < y) swap(x, y);
	while (y)
	{
		int tmp = x % y;
		x = y; y = tmp;
	}
	printf("%d/%d\n", a / x, b / x);
}
int main()
{

#ifndef ONLINE_JUDGE

	freopen("'citing.in", "r", stdin);
	freopen("'citing.out", "w", stdout);
	
#endif

	using namespace Zeonfai;
	n = getInt(); L = getInt();
	for (int i = 0; i < n; ++ i) a[i].w = i, a[i].d = getInt();
	for (int i = 0; i < n; ++ i) a[i].v = getInt();
	sort(a, a + n);
	priority_queue<record> que; 
	que.push(record(0, n - 1)); for (int i = 1; i < n; ++ i) que.push(record(i, i - 1));
	static int nxt[N + 7], lst[N + 7], dd[N + 7];
	memset(dd, 0, sizeof dd);
	for (int i = 0; i < n; ++ i) nxt[i] = (i + 1) % n, lst[i] = (i - 1 + n) % n;
	for (int i = 2; i < n; ++ i)
	{
		record rec;
		while (1)
		{
			rec = que.top(); que.pop();
			int flg = 1;
			for (int j = 0; j < 2; ++ j) if (dd[rec.id[j]]) flg = 0;
			if (flg) break;
		}
		dd[rec.id[1]] = 1;
		nxt[lst[rec.id[1]]] = nxt[rec.id[1]]; lst[nxt[rec.id[1]]] = lst[rec.id[1]];
		nxt[rec.id[1]] = lst[rec.id[1]] = -1;
		que.push(record(rec.id[0], nxt[rec.id[0]])); que.push(record(rec.id[0], lst[rec.id[0]]));
//		printf("%d %d\n", a[rec.id[0]].w, a[rec.id[1]].w);
	}
	record rec;
	while (1)
	{
		rec = que.top(); que.pop();
		int flg = 1;
		for (int j = 0; j < 2; ++ j) if (dd[rec.id[j]]) flg = 0;
		if (flg) break;
	}
//	printf("%d %d\n", a[rec.id[0]].w, a[rec.id[1]].w);
	if (a[rec.id[0]].v > a[rec.id[1]].v) swap(rec.id[0], rec.id[1]); 
	getOutput((a[rec.id[0]].d - a[rec.id[1]].d + L) % L, abs(a[rec.id[1]].v - a[rec.id[0]].v));
}
posted @ 2017-10-05 15:16  Zeonfai  阅读(253)  评论(0编辑  收藏  举报