HDU4393 - 扔钉子
HDU4393 - 扔钉子
题设
【问题描述】
年度学校自行车比赛开始了,ZL是这所学校的学生,他太无聊了,因为他不能骑自行车!因此,他决定干预比赛,他通过以前的比赛视频获得了选手的信息,一个选手第一秒可以跑F米,然后每秒跑S米。每个选手有一条直线跑道,ZL每秒向跑的最远的运动员跑道扔一个钉子,在自行车胎爆炸之后,该选手将被淘汰。如果有多个选手是NO.1,则他总是选择ID最小的选手扔钉子。
【输入形式】
每个测试用例的第一行包含一个整数n(1≤n≤50000),表示选手人数,然后跟随n行,每行包含第i个选手的两个整数Fi(0≤Fi≤500),Si(0<Si≤100),表示该选手第一秒可以跑Fi米,然后每秒跑Si米,i是玩家从1开始的ID。
【输出形式】
输出n个数字,以空格分隔,第i个数字是选手的ID,该选手将在第i秒结束时被淘汰。
【样例输入】
3
100 1
100 2
3 100
【样例输出】
1 3 2
题解
因为本题中的F和S似乎没有主导性,作者采用了链表的方式进行模拟,通过数组来构建了链表,但此法显然速度较慢,时间复杂度为O(n2),只能应付数据较少的情况,通过学校oj平台的测试没有问题。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <cstdio>
const int maxn = 50000 + 10;
int lc[maxn], rc[maxn];
int p[maxn], speed[maxn];
int head;
int main() {
// freopen("in.txt", "r", stdin);
int n;
head = 1;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
int f, s;
scanf("%d %d", &f, &s);
p[i] = f;
speed[i] = s;
rc[i] = i + 1;
lc[i + 1] = i;
if (i == 1) {
lc[i] = -1;
}
if (i == n) {
rc[i] = -1;
}
}
while (1) {
int k = head, max_p = head;
while (k > 0) {
if (p[k] > p[max_p]) {
max_p = k;
}
k = rc[k];
}
printf("%d ", max_p);
if (lc[max_p] < 0 && rc[max_p] < 0) break;
if (lc[max_p] < 0) {
head = rc[max_p];
lc[rc[max_p]] = -1;
} else if (rc[max_p] < 0) {
rc[lc[max_p]] = rc[max_p];
} else {
rc[lc[max_p]] = rc[max_p];
lc[rc[max_p]] = lc[max_p];
}
k = head;
while (k > 0) {
p[k] += speed[k];
k = rc[k];
}
}
}
This post is licensed under CC BY 4.0 by the author.