CF1311E Construct the Binary Tree

膜这场比赛的 \(rk1\)
\(\color{black}A\color{red}{lex\_Wei}\)

这题应该是这场比赛最难的题了

容易发现,二叉树的下一层不会超过这一层的 \(2\) 倍,所以我们先构造出来一颗尽量满的二叉树,然后慢慢向下调整,调整的方法是从最上面一个一个弄下来。

然后你慢慢调整的复杂度最多是 \(d\) ,复杂度 \(O(d)\)

#include <bits/stdc++.h>
using namespace std ;
const int maxn = 5e3 + 5;
int n , d , p[maxn] , fa[maxn] ;
vector < int > dep[maxn] ;

signed main() {
    int t;
    cin >> t ;
    while(t --) {
        memset(p , 0 , sizeof(p)) , memset(fa , 0 , sizeof(fa)) ;
        cin >> n >> d ;
        int sum = 0 , bs = 0 ;
        for(int i = 1 ; i <= n ;) {
            int rem = min(n - i + 1 , 1 << bs) ;
            p[bs] = rem , sum += rem * bs; 
            i += rem , bs ++ ;
        }
        if(sum > d) {
            puts("no") ;
            continue ;
        }
        int pos = bs; 
        while(sum < d) {
            int k = 0 ;
            for(int i = 1 ; i <= n ; i ++) 
                if((p[i] - 1) * 2 >= p[i + 1] + 1) {
                    k = i ;
                    break ;
                }
            if(! k) 
                break ;
            sum ++ , p[k] -- , p[k + 1] ++ ;
        }
        if(sum < d) {
            puts("no") ;
            continue ;
        }
        puts("yes") ;
        int cnt = 1 ;
        for(int i = 0 ; i <= n ; i ++)
            dep[i].clear() ;
        dep[0].push_back(1);
        dep[0].push_back(1);
        for(int i = 1 ; i <= n ; i ++) {
            while(p[i] --) {
                fa[++ cnt] = dep[i - 1].back() ;
                dep[i].push_back(cnt) ;
                dep[i].push_back(cnt) ;
                dep[i - 1].pop_back() ;
            }
        }
        for(int i = 2 ; i <= n ; i ++) 
            cout << fa[i] << ' ' ;
        cout << '\n' ;
    }   
    return 0 ;
}

猜你喜欢

转载自www.cnblogs.com/Isaunoya/p/12374601.html