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;
}

浙公网安备 33010602011771号