CF1311E题解

题意

构造一棵有 \(n\) 个节点的二叉树,使所有点的深度之和为 \(d\),根节点为 \(1\),根节点深度为 \(0\)

思路

深度之和达上界时树为链的形态,达下界时为满二叉树的形态。考虑初始先构造一条链,逐步向满二叉树的形态调整。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int T,n,d,fa[5003],dep[5003],cnt[5003],sum,maxn,cur,now,minn;
vector<int>v[5003];
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin>>T;
	while(T--){
		cin>>n>>d;
		sum=cur=0,maxn=n-1,minn=0,now=n;
		for(int i=2;i<=n;i++)fa[i]=i-1,cnt[i]=1,sum+=(i-1);
		cnt[1]=1,cnt[n]=0;
		for(int i=0;i<n;i++){
			v[i].clear();
			v[i].push_back(i+1);
		}
		int x=n;
		for(int i=0,b=1;x;i++,b*=2)minn+=min(x,b)*i,x-=min(x,b);
		if(sum<d||d<minn){cout<<"No\n";continue;}
		while(sum-maxn+cur+1>d){
			sum=sum-maxn+cur+1;
			int u=v[cur].back();
			cnt[u]++;cnt[fa[now]]--;
			v[cur+1].push_back(now);
			maxn--;
			fa[now]=u;
			now--;
			if(cnt[u]==2)v[cur].pop_back();
			if(!v[cur].size())cur++;
		}
		int dt=sum-d;
		fa[now]=now-dt-1;
		cout<<"Yes\n";
		for(int i=2;i<=n;i++)cout<<fa[i]<<" ";
		cout<<"\n";
	}
	return 0;
}

posted @ 2025-09-29 21:48  PenguinJ  阅读(5)  评论(0)    收藏  举报