P9592 「Daily OI Round 1」Tree

题目描述

给定三个正整数参数 n,d,kn,d,kn,d,k,你需要构造出一棵根节点为 111 的树,满足这棵树有 nnn 个节点,每个节点到根节点的距离和为 ddd,除了叶节点以外每个节点的直接儿子数量至少 kkk 个,且所有节点的最大深度最小。

注意事项:

  • 距离:两个点之间的简单路径上的边的条数。
  • 叶子节点:没有儿子的非根节点。
  • 根节点深度为 000

输入格式

本题有多组数据。

第一行一个正整数 TTT,表示数据组数。
对于每组数据:共一行三个正整数 n,d,kn,d,kn,d,k,含义如题所示。

输出格式

对于每次询问,如果有解,第一行输出 YES,然后一行 n−1n-1n1 个正整数,第 iii 个正整数 aia_iai 表示 aia_iaii+1i+1i+1 的父亲节点,且 ai≤ia_i\leq iaii;如果无解,输出 NO

如果有多组合法的答案,可以任意输出其中一组。

特别地,如果 n=1n=1n=1 且有解,方案输出一行空行即可。

输入输出样例 #1

输入 #1

3
5 4 1
5 6 1
5 7 1

输出 #1

YES
1 1 1 1
YES
1 1 3 3
YES
1 2 2 2

输入输出样例 #2

输入 #2

3
5 4 2
5 6 2
5 7 2

输出 #2

YES
1 1 1 1
YES
1 1 3 3
NO

说明/提示

样例解释

对于第二组样例的第二组询问,n=5,d=6,k=2n=5,d=6,k=2n=5,d=6,k=2,即需要构造出含有 555 个节点,各个节点到节点 111 的距离和为 666 且除叶节点外的节点至少有 kkk 个儿子节点。

下面是样例构造的图:

其中编号为 1,2,3,4,51,2,3,4,51,2,3,4,5 的点到根节点 111 的距离分别为 0,1,1,2,20,1,1,2,20,1,1,2,2,和为 666,满足条件。而且非叶子节点 1,31,31,3 都含有至少 222 个儿子节点,可以证明这是所有合法构造中节点的最大深度最小的解法,在此处为 222

数据范围

本题开启捆绑测试。

Subtask\text{Subtask}Subtask 分值 n≤n \len 特殊性质
000 555 101010
111 555 202020
222 555 10510^5105 k=n−1k= n-1k=n1
333 555 10510^5105 k=n−1k= n-1k=n1n−2n-2n2
444 101010 10510^5105 T=1T=1T=1
555 707070 10510^5105

对于全部数据,保证:1≤n≤1051 \le n \le 10^51n1051≤T≤1051 \le T \le 10^51T1051≤k≤1051 \le k \le 10^51k105∑n≤106\sum n \le 10^6n1061≤d≤10101 \le d \le 10^{10}1d1010

C++实现

#include<bits/stdc++.h>
using namespace std;
#define N 1000005
#define int long long
int n,m,i,j,ans,d,k,a[N],s,l[N],flg,dep,t,f;
signed main(){
	scanf("%lld",&t);
	while(t--){
		for(i=1;i<=n;i++) a[i]=l[i]=0;
		scanf("%lld%lld%lld",&n,&d,&k),f=2,l[1]=1,flg=0,dep=1;
		while(1){
			int nxt=f;
			if(d==0) break;
			for(i=1;i<=k;i++){
				if(f>n){flg=1;break;}
				a[f++]=l[dep];	
			}	
			d-=k*dep;
			if((n-f+1)*dep>=d) break;
			else l[++dep]=nxt;
		}
		if(flg==1 || d<n-f+1) printf("NO\n");
		else{
			printf("YES\n");
			for(i=f;i<=n;i++){
				while(1){
					if(d<dep || d-dep<n-i) dep--;
					else break;
				}
				a[i]=l[dep],d-=dep;
			}
			for(i=2;i<=n;i++) printf("%lld ",a[i]);
			printf("\n");
		}
	}
	return 0;
}

在这里插入图片描述

后续

接下来我会不断用C++来实现信奥比赛中的算法题、GESP考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐