码迷,mamicode.com
首页 > 其他好文 > 详细

炮艇大赛之正式赛

时间:2019-08-05 20:32:51      阅读:64      评论:0      收藏:0      [点我收藏+]

标签:长度   时间   lin   std   bre   一个   表示   queue   ios   

题目

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;
}

炮艇大赛之正式赛

标签:长度   时间   lin   std   bre   一个   表示   queue   ios   

原文地址:https://www.cnblogs.com/2016gdgzoi509/p/11305273.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有 京ICP备13008772号-2
迷上了代码!