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;
}
发布了25 篇原创文章 · 获赞 24 · 访问量 575

猜你喜欢

转载自blog.csdn.net/rainbowsea_1/article/details/104573520