Java (javac)
时间限制
1200 ms
内存限制
512 MB
其他编译器
时间限制
400 ms
内存限制
64 MB
栈限制
8192 KB
题目描述:
有 2 k 2^{k} 2k名选手将要参加一场锦标赛。锦标赛共有 k k k 轮,其中第 i i i 轮的比赛共有 2 k − i 2^{k-i} 2k−i 场,每场比赛恰有两名选手参加并从中产生一名胜者。每场比赛的安排如下:
- 对于第 1 1 1 轮的第 j j j 场比赛,由第 ( 2 j − 1 ) (2j − 1) (2j−1) 名选手对抗第 2 j 2j 2j 名选手。
- 对于第 i i i 轮的第 j j j 场比赛 ( i > 1 ) (i > 1) (i>1),由第 ( i − 1 ) (i − 1) (i−1) 轮第 ( 2 j − 1 ) (2j − 1) (2j−1) 场比赛的胜者对抗第 ( i − 1 ) (i − 1) (i−1) 轮第 2 j 2j 2j 场比赛的胜者。
第
k
k
k 轮唯一一场比赛的胜者就是整个锦标赛的最终胜者。
举个例子,假如共有
8
8
8 名选手参加锦标赛,则比赛的安排如下:
- 第 1 1 1 轮共 4 4 4 场比赛:选手 1 1 1 vs 选手 2 2 2,选手 3 3 3 vs 选手 4 4 4,选手 5 5 5 vs 选手 6 6 6,选手 7 7 7 vs 选手 8 8 8。
- 第 2 2 2 轮共 2 2 2 场比赛:第 1 1 1 轮第 1 1 1 场的胜者 vs 第 1 1 1 轮第 2 2 2 场的胜者,第 1 1 1 轮第 3 3 3 场的胜者 vs 第 1 1 1 轮第 4 4 4 场的胜者。
- 第 3 3 3 轮共 1 1 1 场比赛:第 2 2 2 轮第 1 1 1 场的胜者 vs 第 2 2 2 轮第 2 2 2 场的胜者。
已知每一名选手都有一个能力值,其中第 i i i 名选手的能力值为 a i a_{i} ai 。在一场比赛中,若两名选手的能力值不同,则能力值较大的选手一定会打败能力值较小的选手;若两名选手的能力值相同,则两名选手都有可能成为胜者。
令 l i , j l_{i,j} li,j 表示第 i i i 轮第 j j j 场比赛 败者 的能力值,令 w w w 表示整个锦标赛最终胜者的能力值。给定所有满足 1 ≤ i ≤ k 1 \le i \le k 1≤i≤k 且 1 ≤ j ≤ 2 k − i 1 \le j \le 2^{k-i} 1≤j≤2k−i 的 l i , j l_{i,j} li,j 以及 w w w,请还原出 a 1 , a 2 , ⋯ , a n a_{1}, a_{2}, \cdots, a_{n} a1,a2,⋯,an 。
输入格式:
第一行输入一个整数
k
(
1
≤
k
≤
18
)
k (1 \le k \le 18)
k(1≤k≤18)表示锦标赛的轮数。
对于接下来
k
k
k 行,第
i
i
i 行输入
2
k
−
i
2^{k-i}
2k−i 个整数
l
i
,
1
,
l
i
,
2
,
⋯
,
l
i
,
2
k
−
i
l_{i,1}, l_{i, 2}, \cdots, l_{i,2^{k-i}}
li,1,li,2,⋯,li,2k−i ,其中
l
i
,
j
l_{i,j}
li,j 表示第
i
i
i 轮第
j
j
j 场比赛 败者 的能力值。
接下来一行输入一个整数
w
(
1
≤
w
≤
1
0
9
)
w (1 \le w \le 10^{9})
w(1≤w≤109)表示锦标赛最终胜者的能力值。
输出格式:
输出一行 n 个由单个空格分隔的整数
a
1
,
a
2
,
⋯
,
a
n
a_{1}, a_{2}, \cdots, a_{n}
a1,a2,⋯,an ,其中
a
i
a_{i}
ai 表示第 i 名选手的能力值。如果有多种合法答案,请输出任意一种。如果无法还原出能够满足输入数据的答案,输出一行 No Solution
。
请勿在行末输出多余空格。
输入样例1:
3
4 5 8 5
7 6
8
9
输出样例1:
7 4 8 5 9 8 6 5
输入样例2:
2
5 8
3
9
输出样例2:
No Solution
提示:
本题返回结果若为格式错误均可视为答案错误。
给定k轮比赛中,每场比赛失败者的能力值。
求每个人的能力值
emmmmmmm
模拟
在第一轮比赛的到败者的时候,可以先将前者视作为败者,然后将后者视作为胜者。
然后在之后的每轮中,当前这场比赛的败者能力值 与 上一轮的相应两场比赛(j << 1 与 j << 1 | 1) 的败者能力值 相比
- 都小于,则无法还原
- 大于等于其中一个,则胜者为另一个
- 都大于等于,则随意选一个为胜者
需要注意一点的是:会出现上一轮比赛的败者能力值比这轮败者能力值大的情况。所以需要将上一轮败者的最大能力值更新为本轮败者能力值中。
import java.io.*;
import java.math.*;
import java.util.*;
public class Main
{
public static void main(String[] args) throws IOException
{
int k = ini();
int lost[][] = new int[k + 1][1 << k]; // 存储第i轮j场中的败者的能力值
int win[][] = new int[k + 1][1 << k]; // 存储第i轮j场中的胜者
int ans[] = new int[1 << k]; // 存储每个人的能力值
boolean f = false; // 是否不能还原每个人的能力值
for (int i = 1; i <= k; i++)
{
for (int j = 0; j < (1 << k - i); j++)
{
lost[i][j] = ini();
// 统一前者为败者 后者为胜者
if (i == 1)
{
ans[j << 1] = lost[i][j];
win[i][j] = j << 1 | 1;
continue;
}
// 如果当前败者的能力值,比上一轮的两个败者的能力值低,则无法还原所有人的能力值
if (lost[i][j] < lost[i - 1][j << 1] && lost[i][j] < lost[i - 1][j << 1 | 1])
f = true;
// 如果当前败者的能力值 大于等于 上一轮败者中前者的能力值
if (lost[i][j] >= lost[i - 1][j << 1])
{
win[i][j] = win[i - 1][j << 1 | 1]; // 当前这轮的胜者为 上一轮败者中的后者
ans[win[i - 1][j << 1]] = lost[i][j]; // 那么上一轮胜者的前者能力值为当前能力值
}
else
{
win[i][j] = win[i - 1][j << 1]; // 当前这轮的胜者为 上一轮败者中的前者
ans[win[i - 1][j << 1 | 1]] = lost[i][j]; // 那么上一轮胜者的后者能力值为当前能力值
}
// 将当前败者的能力值替换为最大的败者能力值
lost[i][j] = Math.max(lost[i][j], Math.max(lost[i - 1][j << 1], lost[i - 1][j << 1 | 1]));
}
}
int w = ini();
// 如果胜者的能力值比第k轮的败者能力值低,则无法还原
if (w < lost[k][0])
f = true;
if(f) out.println("No Solution"); // 不能还原
else
{
ans[win[k][0]] = w; // 存入冠军的能力值
// 输出所有人的能力值
for (int i = 0; i < (1 << k); i++)
{
if (i != 0) out.print(" ");
out.print(ans[i]);
}
}
out.flush();
out.close();
}
static StreamTokenizer sc = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter out = new PrintWriter(System.out);
static int ini() throws IOException
{
sc.nextToken();
return (int) sc.nval;
}
}
如果有说错的 或者 不懂的 尽管提 嘻嘻
一起进步!!!