L2 - 047 锦标赛
思路:
将其放入一颗满二叉树上去考虑:从二叉树的最底层开始,每一轮比赛,为同一个祖先的左右两个儿子进行比较,而你需要将败者的能力值填到左右两个儿子其中一个上面,另一个就向上传递表示胜利。(参考单败淘汰制)
可以发现:如果需要对某一个结点进行赋值,充分必要条件是该值大于等于其子树上所有值的最大值,否则的话这个人就会在之前的比赛中就输掉。当一轮比赛中,败者能力值无法赋值到两个人则代表“No solution”。
也就是说:我们需要维护的是每个结点上其子树的最大值。由于是一颗二叉树,所以最大值只需要取两个子树的max即可。同时由于需要输出每个人的能力,所以二叉树中不仅要存最大值信息,还要存胜者编号信息,这样便能直接对败者进行赋值了。
#include<bits/stdc++.h>
using namespace std;
const int N = 20;
int ans[1 << N];
int main(){int n , x;cin >> n;vector<array<int , 2>>pre;for(int i = 1 ; i <= (1 << n) ; i ++){pre.push_back({i , 0});}for(int i = 1 ; i <= n ; i ++){vector<array<int,2>>st;
/* for(auto it : pre){cout << it[0] << " " << it[1] << endl;}*/for(int j = 0 ; j < (1 << (n - i)); j ++){cin >> x;auto tmp1 = pre[j * 2] , tmp2 = pre[j * 2 + 1];int id1 = tmp1[0] , id2 = tmp2[0] , cnt1 = tmp1[1] , cnt2 = tmp2[1];// cout << id1 << id2 << endl;if(x >= cnt1){//放入左儿子ans[id1] = x;st.push_back({id2 , max(x , cnt2)});}else if(x >= cnt2){//放入右儿子ans[id2] = x;st.push_back({id1 , max(x , cnt1)});}else{cout << "No Solution";return 0;}}pre = st;}cin >> x;if(x >= pre[0][1]){ans[pre[0][0]] = x;}else{cout << "No Solution";return 0; }for(int i = 1 ; i <= (1 << n) ; i ++){cout << ans[i] <<" ";}
}