赞
踩
有 2k 名选手将要参加一场锦标赛。锦标赛共有 k 轮,其中第 i 轮的比赛共有 2k−i 场,每场比赛恰有两名选手参加并从中产生一名胜者。每场比赛的安排如下:
第 k 轮唯一一场比赛的胜者就是整个锦标赛的最终胜者。
举个例子,假如共有 8 名选手参加锦标赛,则比赛的安排如下:
已知每一名选手都有一个能力值,其中第 i 名选手的能力值为 ai。在一场比赛中,若两名选手的能力值不同,则能力值较大的选手一定会打败能力值较小的选手;若两名选手的能力值相同,则两名选手都有可能成为胜者。
令 li,j 表示第 i 轮第 j 场比赛 败者 的能力值,令 w 表示整个锦标赛最终胜者的能力值。给定所有满足 1≤i≤k 且 1≤j≤2k−i 的 li,j 以及 w,请还原出 a1,a2,⋯,an。
第一行输入一个整数 k(1≤k≤18)表示锦标赛的轮数。
对于接下来 k 行,第 i 行输入 2k−i 个整数 li,1,li,2,⋯,li,2k−i(1≤li,j≤109),其中 li,j 表示第 i 轮第 j 场比赛 败者 的能力值。
接下来一行输入一个整数 w(1≤w≤109)表示锦标赛最终胜者的能力值。
输出一行 n 个由单个空格分隔的整数 a1,a2,⋯,an,其中 ai 表示第 i 名选手的能力值。如果有多种合法答案,请输出任意一种。如果无法还原出能够满足输入数据的答案,输出一行 No Solution
。
请勿在行末输出多余空格。
- 3
- 4 5 8 5
- 7 6
- 8
- 9
7 4 8 5 9 8 6 5
- 2
- 5 8
- 3
- 9
No Solution
本题返回结果若为格式错误均可视为答案错误。
- 3
- 9 5 8 5
- 6 7
- 8
- 9
9 9 5 6 8 8 5 7
注:此测试点答案唯一
测试点2:有无解,未判断出来,如胜者的能力值比输者小,应该是无解。
将全部比赛看成一颗满二叉树,双亲节点为胜者,左右节点为比赛的二人。
先将输的人放在对应的左节点上。
1.输入,将输者放的对应的左节点上
2.以now为根节点开始判断
2.2.若根节点小于左子树的根节点(该根的左节点),则无解
2.3.将根节点的值给右节点,判断左右节点是否为左右子树的最大值
2.3.1不是,左右节点值对换,再次判断
2.3.1.1还不是则无解
3.输出最后一层的结点
- #include <cstdio>
- #include <iostream>
- #include <algorithm>
- #include <cstring>
-
- using namespace std;
-
- int tree[1 << 19];
- int n,m;
-
- void print()//输出整棵树,测试用
- {
- for(int i = 1;i < m;i++)
- cout << tree[i] <<" ";
- cout << endl;
- }
- int find(int u)//找出以u为根的子树的最大值
- {
- if(u >= m) return 0;
- int t = max(find(u * 2),find(u * 2 + 1));
-
- if(t > tree[u]) return t;
- return tree[u];
- }
-
- int main()
- {
- scanf("%d",&n);
- m = (1 << (n + 1));//m - 1为最大下标
-
- for(int i = n;i > 0;i--)//j为左节点编号,k为该层有几个左节点
- for(int j = 1 << i,k = 1 << (i - 1);k;k--,j+=2)
- scanf("%d",&tree[j]);//先将值放在对应的左节点上
- scanf("%d",&tree[1]);//根节点
-
- for(int i = 0;i < n;i++)//
- {
- int h = 1 << i;//该层第一个节点的编号
- for(int j = 0;j < (1 << i);j++)
- {
- int now = h + j;//节点编号
- if(tree[now] < tree[now * 2])//赢的人比输的人的能力值小,无解
- {
- puts("No Solution");
- return 0;
- }
-
- tree[now * 2 + 1] = tree[now];//先放右节点上
- int l = find(now * 2),r = find(now * 2 + 1);//l,r分别为左右子树的最大值
- if(tree[now * 2] != l || tree[now] != r)//左右节点不是左右子树的最大值
- {
- swap(tree[now * 2],tree[now * 2 + 1]);//换一下看看
- l = find(now * 2),r = find(now * 2 + 1);
- if(l != tree[now * 2] || r != tree[now *2 + 1])//还不是,则无解
- {
- puts("No Solution");
- return 0;
- }
- }
- }
- }
- for(int i = 1 << n;i < m;i++)//输出最后一层
- printf("%d%s",tree[i],(i == m - 1 ? "\n" : " "));
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。