GPLT(有空就写)

L2 - 047 锦标赛

GPLT(有空就写)_第1张图片

思路:

        将其放入一颗满二叉树上去考虑:从二叉树的最底层开始,每一轮比赛,为同一个祖先的左右两个儿子进行比较,而你需要将败者的能力值填到左右两个儿子其中一个上面,另一个就向上传递表示胜利。(参考单败淘汰制)

        可以发现:如果需要对某一个结点进行赋值,充分必要条件是该值大于等于其子树上所有值的最大值,否则的话这个人就会在之前的比赛中就输掉。当一轮比赛中,败者能力值无法赋值到两个人则代表“No solution”。

        也就是说:我们需要维护的是每个结点上其子树的最大值。由于是一颗二叉树,所以最大值只需要取两个子树的max即可。同时由于需要输出每个人的能力,所以二叉树中不仅要存最大值信息,还要存胜者编号信息,这样便能直接对败者进行赋值了。

        

#include
using namespace std;
const int N = 20;
int ans[1 << N];
int main(){
    int n , x;
    cin >> n;
    vector>pre;
    for(int i = 1 ; i <= (1 << n) ; i ++){
        pre.push_back({i , 0});
    }
    for(int i = 1 ; i <= n ; i ++){
        vector>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] <<" ";
    }
}

你可能感兴趣的:(c++,算法)