链接:E-小红的ds题_牛客周赛 Round 92
来源:牛客网题目描述
\hspace{15pt}小红希望你构造一棵层数为 nnn 的二叉树,其第 iii 层恰好有 aia_iai 个节点。你能帮帮她吗?
\hspace{15pt}一棵树被称为二叉树,当且仅当其满足:
∙ \hspace{23pt}\bullet\,∙每个节点要么没有父节点连接(此时该节点被称为根节点)、要么被 111 个父节点连接(此时该节点被称为父节点的子节点);
∙ \hspace{23pt}\bullet\,∙每个节点连接的子节点数量要么为 000(此时该节点被称为叶子节点)、要么小于等于 222(此时该节点被称为分支节点)。输入描述:
\hspace{15pt}第一行输入一个正整数 n(1≦n≦104)n \left(1 \leqq n \leqq 10^4\right)n(1≦n≦104),代表二叉树的层数。 \hspace{15pt}第二行输入 nnn 个正整数 a1,a2,…,an(1≦ai≦105)a_1,a_2,\dots,a_n \left(1 \leqq a_i \leqq 10^5\right)a1,a2,…,an(1≦ai≦105),代表二叉树的第 iii 层的节点数量限制。保证 a1=1a_1 = 1a1=1,且对于 2≦i≦n2 \leqq i \leqq n2≦i≦n,均有 ai≦ai−1×2a_i \leqq a_{i-1} \times 2ai≦ai−1×2。 \hspace{15pt}除此之外,保证单个测试文件的 aia_iai 之和不超过 10510^5105。输出描述:
\hspace{15pt}第一行输出一个正整数 p(1≦p≦n)p \left(1 \leqq p \leqq n\right)p(1≦p≦n),代表根结点的编号。编号从 111 开始。 \hspace{15pt}此后输出 ∑i=1nai\sum\limits_{i=1}^n a_ii=1∑nai 行,第 iii 行输出两个元素 li,ril_i,r_ili,ri,分别代表 iii 号节点的左儿子和右儿子的编号。特别的,如果不存在左儿子/右儿子,则输出 −1-1−1 替代这个编号。 \hspace{15pt}如果存在多个解决方案,您可以输出任意一个,系统会自动判定是否正确。注意,自测运行功能可能因此返回错误结果,请自行检查答案正确性。示例1
输入
复制3 1 2 3
3 1 2 3输出
复制4 -1 -1 1 -1 6 5 2 3 -1 -1 -1 -1
4 -1 -1 1 -1 6 5 2 3 -1 -1 -1 -1说明
完整题目可以跳转一下,官方题解给的很清晰了,题目也清晰。不过确实喜欢这道题,姑且讲讲,也提高自己。
阅读题意:每一层有限定的节点,那么我们需要先安排那些节点编号在哪一层?
我们直接顺序遍历,从上到下,从左到又,从1,2,3,.......;
int cnt=0; vector<vector<int>>f(n+5); for(int i=1;i<=n;i++){ cin>>a[i]; k+=a[i]; for(int j=0;j<a[i];j++)f[i].push_back(++cnt); }f[i]的意思是第几层,里面装的每一层所有节点的编号。
那么第二步,就是分配咯。二叉树,每一个节点只能最多有叶子节点2个,怎么分配,上下两层都从左到右咯。那么我们用mx来记录下一层的节点数量,也就是这一层需要对接的节点数量,同时我们需要保证这个节点的儿子不超过两个。
vector<vector<int>>g(n+5); for(int i=1;i<=n-1;i++){ int mx=a[i+1],now=0;//这一层节点需要对接的叶子节点 for(int j=0;j<f[i].size();j++){ if(now<mx&&g[f[i][j]].size()<2)g[f[i][j]].push_back(f[i+1][now]),++now;//加入下一层的节点,now来记录加到第几个 if(now<mx&&g[f[i][j]].size()<2)g[f[i][j]].push_back(f[i+1][now]),++now;//加入下一层的节点,now来记录加到第几个 //写两个是因为一个节点最多进入两个if,我们刚好让他一次走完; } }用now来记录这一层对接下一层到了那个位置,到了mx-1可以停止,因为now==mx-1时候,就是加入了mx个节点。同时g[i][j]的表达第i层第j个节点的儿子节点,我们将儿子节点存入,后续答案从这里输出,这个节点的儿子节点数量也从这里判断。
cout << 1 << endl; //定1是根 for(int i = 1; i <= k; ++i){ if(g[i].size() == 2) cout << g[i][0] << " " << g[i][1] << endl; else if(g[i].size() == 1) cout << g[i][0] << " -1" << endl; else cout << "-1 -1" << endl; }本题得解,很基础的层序二叉树遍历,记得开两个二维是真的,数据变量多。
附上完整代码