Codeforces Round #624 (Div. 3) problem E

Codeforces Round #624 (Div. 3) problem E

Description:
You are given two integers nnn and ddd. You need to construct a rooted binary tree consisting of n vertices with a root at the vertex 111 and the sum of depths of all vertices equals to ddd.
A tree is a connected graph without cycles. A rooted tree has a special vertex called the root. A parent of a vertex vvv is the last different from v vertex on the path from the root to the vertex v. The depth of the vertex vvv is the length of the path from the root to the vertex vvv. Children of vertex v are all vertices for which v is the parent. The binary tree is such a tree that no vertex has more than 222 children.
You have to answer t independent test cases.
Input
The first line of the input contains one integer t(1≤t≤1000)t (1≤t≤1000)t(1≤t≤1000) — the number of test cases.
The only line of each test case contains two integers nnn and d(2≤n,d≤5000)d (2≤n,d≤5000)d(2≤n,d≤5000)— the number of vertices in the tree and the required sum of depths of all vertices.
It is guaranteed that the sum of nnn and the sum of ddd both does not exceed 500050005000 (∑n≤5000,∑d≤5000)(∑n≤5000,∑d≤5000)(∑n≤5000,∑d≤5000).
Output
For each test case, print the answer.
If it is impossible to construct such a tree, print “NO” (without quotes) in the first line. Otherwise, print “{YES}” in the first line. Then print n−1 integers p2,p3,…,pn in the second line, where pi is the parent of the vertex i. Note that the sequence of parents you print should describe some binary tree.
Example
input
3
5 7
10 19
10 18
1
2
3
4
output
YES
1 2 1 3
YES
1 2 3 3 9 9 2 1 6
NO
1
2
3
4
5
Note
Pictures corresponding to the first and the second test cases of the example:

题意
n为结点的个数,d为深度和
样例一

在这里插入图片描述
深度和 = 1+1+2 +3= d = 7

这种情况下 2 ~ 5 的父亲结点 为 1 2 1 3;

当然也可以不这样放置结点
在这里插入图片描述
这种情况下 2 ~ 5 的父亲结点 为 1 1 2 4;

题解

#include <bits/stdc++.h> 
#define P pair<int, int>
using namespace std; 
int const N = 5007;
int level[N];
int p[N];
queue<P> q;

int getMinimum(int n) {	//最小深度值
	n--;	
	int res = 0;	
	int ctr = 1; 	
	for (int i = 2; n != 0; i*=2, ctr++)		
		res += min(i, n) * ctr, n -= min(i, n);	
	return res;
} 
	
int getMaximum(int n){	//最大深度值
	return (n * (n-1)) / 2;
}

int main(){	
 	int t; 
 	cin >> t;	
 	int n, d; 	
 	//判断可不可以生成二叉树
	for (int i = 0; i < t; ++i) {	
 		cin >> n >> d;		
		if (d < getMinimum(n) || getMaximum(n) < d) {
			cout << "NO\n";			
 			continue;		
 		} 		
	cout << "YES\n";
			
	for (int i = 0; i < n; ++i)			
 		level[i] = 1;	
 	int dif = getMaximum(n) - d; 	
	int idx = 1;				
	for (int i = n-1; i >= 0; --i)	{			
 		if (i - idx < dif) level[i]--, level[idx]++, dif -= (i - idx);			
 		else level[i]--, level[i-dif]++, dif = 0;			
		if (level[idx] == 2 * level[idx-1]) idx++;		
 		if (dif == 0) break;		
 	}
 	 		
	while (q.size()) q.pop();		
 	q.push(P(1, 1)); 		
 	int node = 2;	
 	for (int i = 1; i < n;)	{			
 		if (level[i] == 0) {
 			++i; continue;
 		} 	 			
 		while (i > q.front().first) q.pop();			
		 if (level[i] == 1)			
 			p[node] = q.front().second, q.push(P(i+1, node)), node++, q.pop(), level[i] = 0;			
	 	else {				
			p[node] = q.front().second, q.push(P(i+1, node)), node++;			
 			p[node] = q.front().second,q.push(P(i+1, node)), node++;						q.pop();				
	 		level[i] -= 2;			
 		}	
 	} 		
 	for (int i = 2; i < n; ++i)				
		cout << p[i] << ' ';		
	cout << p[n] << '\n';
 	}		
	return 0;
}

我的代码

#include <bits/stdc++.h>

using namespace std;

const int MAX = 5e3 + 5;
int T, n, d;
int m;
int cnt[ MAX ];

 
struct Node{
        int layer, nu, v;
};
 

int  MAXSUM (int n) {
        n--;
        return (n + 1) * n / 2;       
}


int MINSUM (int n) {
        n--;
        int ans = 0;
        m = 1;
        for (int i = 2; i <= n; n-= i, i <<= 1) {
                 ans += i * (m++);
                 cnt[m] = i;
        }
        if(n > 0) {
                 ans += n *(m++);
                 cnt[m] = n;
        }
        return ans;
}

int main() {
        scanf("%d", &T);
        while(T--) {
                 scanf("%d %d", &n, &d);

                 memset(cnt, 0, sizeof(cnt));                 

                 if(d < MINSUM (n) || d > MAXSUM (n)) {
                         printf("NO\n");

                         continue;
                 }
                 
                 printf("YES\n")
                 int dex = MINSUM (n);
                 while(dex < d) {
                         for (long long i = m ; i >= 1; i--) {
                                  if(cnt[i] > cnt[i + 1] && cnt[i] > 1) {
                                          cnt[i]--;
                                          cnt[i + 1]++;
                                          dex++;
                                          m++;
                                          break;
                                  }
                         }
                 }                
                 Node node[MAX];           
                 node[1].layer = 1, node[1].nu = 1, node[1].v = 1;
                 int num = 2;
                 for (int i = 1; i <= m; i++) {
                         for (int j = 1; j <= cnt[i]; j++) {
                                  node[num].layer = i + 1;
                                  node[num].nu = j;
                                  node[num].v = num;
                                  //cout << num << " " << node[num].layer << " " <<  i + 1<< endl;
                                  num++;
                         }                                                           
                 }
                 //cout << node[2].layer << " " << node[3].layer << endl;
                 for (int i = 2; i < num; i++) {
                         if(i <= 3 && node[i].layer == 3) printf("1 ");
                         else {
                                  for (int j = 2; j < num; j++) {
                                          if(((node[i].layer - 1) == node[j].layer) && (node[i].nu + 1) / 2 == node[j].nu ) { 
                                                 printf("%d", node[j].v);
                                                  break;
                                          }
                                  }
                         }
                 }
                 printf("\n");                      
        }
        return 0;
}
#include<bits/stdc++.h>

using namespace std; 
const int N = 5e3 + 10;
int T , n , d , p[N] , dep[N] , tree[N][N] , cnt[N] , sum , Max; 

int main(){
        scanf("%d" ,&T); while(T--){

                 memset(p , 0 ,sizeof(p));
                 memset(cnt , 0, sizeof(cnt));

                 dep[1] = sum =Max = 0;
                 scanf("%d%d" , &n , &d);
                 tree[0][++cnt[0]]= 1;
                 for(int i = 1;i <= n; i++){
                         int LS= i << 1 , RS = i << 1 | 1; // RS = i<<1 + 1;
                         if(LS<= n) dep[LS] = dep[i] + 1 ,tree[dep[LS]][++cnt[dep[LS]]] = LS , sum +=dep[LS] , Max = max(Max , dep[LS]);

                         if(RS<= n) dep[RS] = dep[i] + 1 ,tree[dep[RS]][++cnt[dep[RS]]] = RS , sum +=dep[RS] , Max = max(Max ,dep[RS]);

                 }
                 if(sum > d|| d > n * (n - 1) / 2){ puts("NO"); continue; }                 while(sum <d){

                         for(inti = Max; i >= 0; i--){
                                  if(cnt[i]>= 2 && cnt[i + 1] < (cnt[i] - 1) * 2){
                                          tree[i+ 1][++cnt[i + 1]] = tree[i][cnt[i]] , cnt[i]-- , sum++;
                                          Max= max(Max , i + 1);
                                          break;
                                  }
                         }
                 }
                 for(int k = 0; k < Max; k++)
                         for(int i = 1; i <= cnt[k]; i++){
                                  int LS = 2 * (i - 1) + 1 , RS = 2 * (i - 1) + 2;                                  if(LS <= cnt[k + 1]) p[tree[k + 1][LS]] = tree[k][i];
                                  if(RS <= cnt[k + 1]) p[tree[k + 1][RS]] = tree[k][i];
                         }
                 puts("YES");
                 for(int i = 2;i <= n; i++) printf("%d " , p[i]);
                 puts("");
        }
        return 0;
}
 
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define il inline
#define it register int
#define inf 0x3f3f3f3f
#define lowbit(x) (x)&(-x)
#define mem(a,b) memset(a,b,sizeof(a))
#define mod 998244353
const int N=5e3+10;
int n,d;
int fa[N];
int son[N];
int de[N];//某层的空置位
int dp[N];//dp[i]: i节点在dp[i]层
int main() {
    de[1]=1;
    int t;
    cin>>t;
    while(t--) {     
	scanf("%d%d",&n,&d);       
	memset(de,0,sizeof(de));
        de[1]=1;
        int s=0;
        for(int i=1;i<=n;i++) s+=i-1;//一条链
        int now=1;
        for(int i=1;i<=n;i++){
        	dp[i]=dp[i-1]+1;//下一个节点在i-1的下一层
        	de[dp[i]]--;//单链  去掉这层的一个空置位           
		if(s-(n-i+1)>=d) {//i节点往上跳一层,后面的全部往上跳一层,所以是n-i+1              
			if(de[dp[i]-1]) {//因为是往上跳一层,那么看上一层的空置位是否有                   
				s-=(n-i+1);                   
				de[dp[i]-1]--;//挂在dp[i]-1 层上,所以de[dp[i]-1]的空置位减一                   
				de[dp[i]]++;//dp[i]层的空置位+1 抵消掉32行的减一                   
				dp[i]--;//i节点成功到上一层
                	}
           	 }
           	 de[dp[i]+1]+=2;          
        }
        if(s!=d) {           
		printf("NO\n");
        	continue;
        }
        int flag=1;
               
	memset(son,0,sizeof(son));
        for(int i=2;i<=n;i++){
            fa[i]=0;
            for(int j=1;j<i;j++){               
		if(son[j]<2&&dp[i]==dp[j]+1) {
                    son[j]++;
                    fa[i]=j;
                    break;
                }
            }
            if(fa[i]==0) {
                flag=0;break;
            }
        }
        if(flag==0) {
           	printf("NO\n");
        }
        else
	printf("YES\n");
        for(int i=2;i<=n;i++) 
        	printf("%d ",fa[i]);
        printf("\n");
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值