[蓝桥杯 2019 省 AB] 完全二叉树的权值
题目描述
给定一棵包含 N N N 个节点的完全二叉树,树上每个节点都有一个权值,按从上到下、从左到右的顺序依次是 A 1 , A 2 , ⋯ A N A_1,A_2, \cdots A_N A1,A2,⋯AN,如下图所示:
现在小明要把相同深度的节点的权值加在一起,他想知道哪个深度的节点权值之和最大?如果有多个深度的权值和同为最大,请你输出其中最小的深度。
注:根的深度是 1 1 1。
输入格式
第一行包含一个整数 N N N。
第二行包含 N N N 个整数 A 1 , A 2 , ⋯ , A N A_1,A_2, \cdots, A_N A1,A2,⋯,AN。
输出格式
输出一个整数代表答案。
样例 #1
样例输入 #1
7
1 6 5 4 3 2 1
样例输出 #1
2
提示
对于所有评测用例, 1 ≤ N ≤ 1 0 5 1 \le N \le 10^5 1≤N≤105, 0 ≤ ∣ A i ∣ ≤ 1 0 5 0 \le |A_i| \le 10^5 0≤∣Ai∣≤105。
蓝桥杯 2019 省赛 A 组 F 题(B 组 G 题)。
思路
利用完全二叉树的性质:完全二叉树的每一层(除了可能的最后一层)都是完全填充的。这意味着在深度 d d d处,节点的数量最多是 2 d − 1 2^{d-1} 2d−1。
首先,读取完全二叉树的节点数 n n n。定义几个变量,包括当前深度 d d d、当前层的权值之和 s u m sum sum、最大权值之和 w m a x wmax wmax以及对应的最大深度 d m a x dmax dmax。
接着,开始遍历完全二叉树的每一层。每一层的节点数是 2 d − 1 2^{d-1} 2d−1,其中 d d d是当前深度。然后,读取每个节点的权值,累加到当前层的权值之和 s u m sum sum中。
在遍历完一层后,比较当前层的权值之和 s u m sum sum与最大权值之和 w m a x wmax wmax,如果 s u m sum sum更大,则更新最大权值之和 w m a x wmax wmax和对应的最大深度 d m a x dmax dmax。
最后,将最大深度 d m a x dmax dmax输出。
注意
完全二叉树不一定是满二叉树,最后一层不一定是完全填充的。所以最后一层的节点的数量可能不是 2 d − 1 2^{d-1} 2d−1。当所有节点已经读取完毕后,应该停止输入,否则无法通过部分测试点。
AC代码
#include <algorithm>
#include <cmath>
#include <iostream>
#define AUTHOR "HEX9CF"
using namespace std;
using ll = long long;
const int N = 1e6 + 7;
const int INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n;
cin >> n;
int d = 1;
ll wmax = 0;
int dmax = 0;
for (int i = 1; i <= n;) {
ll sum = 0;
for (int j = 1; j <= pow(2, d - 1) && i <= n; j++) {
int a;
cin >> a;
sum += a;
i++;
}
// cout << sum << "\n";
if (sum > wmax) {
wmax = sum;
dmax = d;
}
d++;
}
cout << dmax << "\n";
return 0;
}