• 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
    ", 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
    ", 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
    ", 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));
    }
    
  • 相关阅读:
    修改带!important的css样式
    解决Eclipse导入项目是提示错误:Some projects cannot be imported because they already exist in the workspace
    HTML5——canvas:使用画布绘制卡片
    vue:更改组件样式
    导入导出大量excel文件
    winfrom控件Treeview绑定数据库中的资料(节点控件)
    Winfrom将excel中的数据导入sqlserver数据库中的方法
    C# 将DataTable表中的数据批量插入到数据库表中的方法
    创建Sql数据表的sql代码
    Winfrom之SplitContainer控件
  • 原文地址:https://www.cnblogs.com/ZeonfaiHo/p/7629239.html
Copyright © 2020-2023  润新知