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 ;
}
posted @ 2020-02-27 21:43  _Isaunoya  阅读(123)  评论(1编辑  收藏  举报