HDU 6136 Death Podracing

题意

给定长l的环上的n个人,每个人有给不相同的速度和位置,相遇时编号大的存活,问最后留存一个人时的时间

做法

直接用堆来模拟即可

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

struct Frac {
    LL fz, fm;
    Frac() {}
    template<class T> Frac(T a):fz(a), fm(1) {}
    template<class T> Frac(T a, T b):fz(a), fm(b) {}
    Frac norm() {
        if (fz < 0 && fm < 0)
            fz = -fz, fm = -fm;
        return Frac(fz, fm);
    }
    Frac operator + (Frac rhs) {
        return Frac(fz * rhs.fm + fm * rhs.fz, rhs.fm * fm).norm();
    }
    Frac operator - (Frac rhs) {
        return Frac(fz * rhs.fm - fm * rhs.fz, rhs.fm * fm).norm();
    }
    Frac operator * (Frac rhs) {
        return Frac(fz * rhs.fz, fm * rhs.fm).norm();
    }
    Frac operator / (Frac rhs) {
        return Frac(fz * rhs.fm, fm * rhs.fz).norm();
    }
};
Frac operator - (int a, Frac b) {
    return Frac(a) - b;
}
Frac operator + (int a, Frac b) {
    return Frac(a) + b;
}
Frac operator / (int a, Frac b) {
    return Frac(a) / b;
}
bool operator < (const Frac&a, const Frac&b) {
    return a.fz * b.fm < a.fm * b.fz;
}
bool operator > (const Frac&a, const Frac&b) {
    return a.fz * b.fm > a.fm * b.fz;
}
bool operator <= (const Frac&a, const Frac&b) {
    return a.fz * b.fm <= a.fm * b.fz;
}

ostream& operator << (ostream&os, Frac a) {
    LL d = __gcd(a.fz, a.fm);
    return os << (a.fz / d) << ‘/‘ << (a.fm / d);
}
istream& operator >> (istream&is, Frac&a) {
    LL d;
    is >> d;
    a = d;
    return is;
}

const int N = 1e5 + 100;

int n, l;
struct Ant {
    int id;
    Frac p, v;
    bool operator < (const Ant&rhs) const {
        return p < rhs.p;
    }
} a[N];

struct Node {
    Node *suc, *pre;
    Ant* a;
} nd[N];

struct Info {
    Frac tim;
    Node *a, *b;
    Info() {}
    Info(Frac tim, Node*a, Node*b):tim(tim), a(a), b(b) {}
    bool operator < (const Info&rhs) const {
        return tim > rhs.tim;
    }
};
priority_queue<Info> pq;
bool del[N];

Frac getTime(Ant a, Ant b) {
    Frac v = b.v - a.v;
    Frac d = b.p - a.p;
    if (d < 0)
        d = d + l;
    if (v > 0) {
        d = l - d;
    } else d = 0 - d;
    return d / v;
}

int main() {
#ifdef lol
    freopen("d.in", "r", stdin);
    freopen("d.out", "w", stdout);
#endif

    ios_base::sync_with_stdio(false);
    cin.tie(0);
    int T; cin >> T;
    while (T--) {
        cin >> n >> l;
        for (int i = 1; i <= n; ++i)
            cin >> a[i].p;
        for (int i = 1; i <= n; ++i) {
            cin >> a[i].v;
            a[i].id = i;
        }
        sort(a + 1, a + n + 1);

        while (!pq.empty()) pq.pop();
        memset(del, 0, sizeof del);

        for (int i = 2; i <= n; ++i) {
            nd[i].pre = &nd[i - 1];
            nd[i - 1].suc = &nd[i];
            nd[i].a = &a[i];
            pq.push(Info(getTime(a[i - 1], a[i]), &nd[i - 1], &nd[i]));
        }
        nd[1].pre = &nd[n];
        nd[n].suc = &nd[1];
        nd[1].a = &a[1];
        pq.push(Info(getTime(a[n], a[1]), &nd[n], &nd[1]));
        Frac ans = 0;
        while (!pq.empty()) {
            Info u = pq.top();
            pq.pop();
            if (del[u.a->a->id] || del[u.b->a->id])
                continue;
            if (u.a->a->id == u.b->a->id) break;
            ans = max(ans, u.tim);
            if (u.a->a->id > u.b->a->id) {
                del[u.b->a->id] = true;
                u.b->suc->pre = u.a;
                u.a->suc = u.b->suc;
                pq.push(Info(getTime(*u.a->a, *u.a->suc->a), u.a, u.a->suc));
            } else {
                del[u.a->a->id] = true;
                u.a->pre->suc = u.b;
                u.b->pre = u.a->pre;
                pq.push(Info(getTime(*u.b->pre->a, *u.b->a), u.b->pre, u.b));
            }
        }
        cout << ans << endl;
    }

    return 0;
}
时间: 2024-07-31 21:11:21

HDU 6136 Death Podracing的相关文章

hdu 6136 Death Podracing(模拟)

题目链接:hdu 6136 Death Podracing 题意: 有n个人在一个环形的跑道上,第i个人有一个power i,每个人有一个起始点和一个不同的速度. 如果两个人相遇,那么power大的那个人就会将power小的那个人淘汰出局. 然后问决出胜负需要多少时间. 题解: 显然,每次有人被淘汰出局的时候,都是被相邻的人干掉的,那么我们先预处理出相邻的人相遇的时间,然后扔进优先队列里面,每次选择最小的时间,将一个人淘汰掉,然后再更新一下当前的局势就行了. 1 #include<bits/st

HDU 6136 Death Podracing(循环链表)

[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6136 [题目大意] 一堆人在操场上跑步,他们都有一定的速度和初始位置, 当两个人相遇的时候编号较小的就会出局,当场上剩下最后一个人的时候游戏结束, 问时长为多少 [题解] 我们发现每次发生碰撞的一定是相邻的两个人, 所以我们找出相邻关系中最先发生碰撞的,将碰撞失败的那个人删除, 之后继续这个过程, 按照上述的做法我们建立一个循环链表,把所有人串起来, 当发生淘汰的时候把那个人从循环链表中删去即可

HDU 6136 Death Podracing (堆)

题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=6136 题解 完了,普及题都不会做了... 发现一个重要性质是只有相邻的人才会相撞,于是直接拿堆维护即可... WA了好几发... 代码 #include<cstdio> #include<cstdlib> #include<cstring> #include<queue> #include<algorithm> #define llong long

2016 Multi-University Training Contest 10 || hdu 5860 Death Sequence(递推+单线约瑟夫问题)

题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5860 题目大意:给你n个人排成一列编号,每次杀第一个人第i×k+1个人一直杀到没的杀.然后剩下的人重新编号从1-剩余的人数.按照上面的方式杀.问第几次杀的是谁. 分析 一轮过后和原来问题比只是人的编号发生变化,故可以转化为子问题求解,不妨设这n个人的编号是0~n-1,对于第i个人,如果i%k=0,那么这个人一定是第一轮出列的第i/k+1个人:如果i%k!=0,那么这个人下一轮的编号就是i

HDU 5860 Death Sequence (递推)

题意:n个人排成一行,从第一个人开始,每个k个人报数,报到数的人被杀死,剩下的人重新排成一行再报数.一共q个询问,每次询问第qi个死的人是谁. 析:是一个约瑟夫的变形,我们要考虑子问题的问题同样编号是0-n-1,如果在某一轮,第 i 个人如果能取模 k 为0,那么这一轮他就会被干掉,如果不是 那么下一轮他就是编号为 i-i/k-1,然后再处理每一轮多少个人被干掉,就OK了. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000&q

HDU 5860 Death Sequence

用线段树可以算出序列.然后o(1)询问. #pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #include&l

HDU 5129 Yong Zheng&#39;s Death

题目链接:HDU-5129 题目大意为给一堆字符串,问由任意两个字符串的前缀子串(注意断句)能组成多少种不同的字符串. 思路是先用总方案数减去重复的方案数. 考虑对于一个字符串S,如图,假设S1,S2,S3,S4,S5,S6均为前缀. 换言之,对于这种字符串,我们计算了三次. 发现,重复的方案数,等于中间如图有颜色的方块的数量.所以我们要做的也就是计数像图中有颜色的小方块的数量. 我们可以通过遍历像S6一样的字符串的数量,来计算重复的方案数.S6满足以下条件: 存在一个前缀S4为S6的后缀,且S

字符串(AC自动机):HDU 5129 Yong Zheng&#39;s Death

Yong Zheng's Death Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 512000/512000 K (Java/Others)Total Submission(s): 224    Accepted Submission(s): 37 Problem Description Some Chinese emperors ended up with a mysterious death. Many historia

hdu 1879 继续畅通工程 (并查集+最小生成树)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1879 继续畅通工程 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 14075    Accepted Submission(s): 6136 Problem Description 省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公