炮艇大赛之正式赛

Posted 2016gdgzoi509

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了炮艇大赛之正式赛相关的知识,希望对你有一定的参考价值。

题目

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;

以上是关于炮艇大赛之正式赛的主要内容,如果未能解决你的问题,请参考以下文章

2022年全国职业院校技能大赛赛项正式赛卷

2022年 全国职业院校技能大赛(中职组)网络安全赛项 正式赛卷 A模块 做题记录

CSDN 软件开发新手赛正式启动,召集热爱编程的你

CSDN 软件开发新手赛正式启动,召集热爱编程的你

数据科学家集结!「合Z之力 解锁极智境界」惠普Z系列算法大赛正式启航

5月10日12点,看雪.深信服2021 KCTF春季赛正式开赛!