Codeforces Round #624 (Div. 3) 比赛人数6075
[codeforces 1311E] Construct the Binary Tree 一条路走到底 完全二叉树+链
总目录详见https://blog.csdn.net/mrcrack/article/details/103564004
在线测评地址https://codeforces.ml/contest/1311/problem/E
Problem | Lang | Verdict | Time | Memory |
---|---|---|---|---|
E - Construct the Binary Tree | GNU C++11 | Accepted | 31 ms | 0 KB |
手模了一下,发现深度和的最大值是链,深度和的最小值是完全二叉树
NO比较容易处理
最大值(n-1+1)*(n-1)/2
最小值2^k-1<=n<=2^(k+1)-1;2^1*1+2^2*2+2^3*3+...+(n-(2^k-1))*k
手工能比较快的画出符合条件的二叉树,不过,编程,感觉比较困难。
n=6,sum=[8,15]演化过程如下图
根据演化过程,编码如下:
#include <cstdio>
#include <algorithm>
#include <cstring>
#define maxn 5010
using namespace std;
int used[maxn],fa[maxn],dep[maxn],node[maxn];
int main(){
int t,n,d,i,maxd,now,pre;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&d);
fa[1]=0,maxd=0,dep[1]=0,memset(used,0,sizeof(used));
for(i=2;i<=n;i++){//构造完全二叉树
fa[i]=i/2;//fa[i]=j 节点i的父亲是j
dep[i]=dep[i/2]+1;//dep[i]=j 节点i的深度是j
d-=dep[i];
maxd=max(maxd,dep[i]);//最大深度
}
if(d<0){//完全二叉树对应着和值最小
printf("NO\n");
continue;
}
now=n;
while(now){//找到最深链
node[dep[now]]=now;//node[i]=j 链上深度为i对应节点j
used[now]=1;//used[i]=1 节点i已经在链上了
now=fa[now];
}
for(i=n;i>=1;i--){//完全二叉树逐渐向链转变
if(used[i])continue;
pre=maxd;
while(dep[i]<=pre&&d){//dep[i]<=pre没有增加链的长度,d>0还有和值
fa[i]=node[dep[fa[i]]+1];
dep[i]+=1;
if(dep[i]>maxd)maxd=dep[i],node[maxd]=i;//节点i已经将链增长了1
d--;
}
}
if(d>0){//链是最长,若还有剩,则不现实
printf("NO\n");
continue;
}
printf("YES\n");
for(i=2;i<=n;i++)printf("%d ",fa[i]);
printf("\n");
}
return 0;
}