【洛谷 P8681】[蓝桥杯 2019 省 AB] 完全二叉树的权值 题解(完全二叉树+数学)

140 阅读2分钟

[蓝桥杯 2019 省 AB] 完全二叉树的权值

题目描述

给定一棵包含 NN 个节点的完全二叉树,树上每个节点都有一个权值,按从上到下、从左到右的顺序依次是 A1,A2,ANA_1,A_2, \cdots A_N,如下图所示:

现在小明要把相同深度的节点的权值加在一起,他想知道哪个深度的节点权值之和最大?如果有多个深度的权值和同为最大,请你输出其中最小的深度。

注:根的深度是 11

输入格式

第一行包含一个整数 NN

第二行包含 NN 个整数 A1,A2,,ANA_1,A_2, \cdots, A_N

输出格式

输出一个整数代表答案。

样例 #1

样例输入 #1

7
1 6 5 4 3 2 1

样例输出 #1

2

提示

对于所有评测用例,1N1051 \le N \le 10^50Ai1050 \le |A_i| \le 10^5

蓝桥杯 2019 省赛 A 组 F 题(B 组 G 题)。


思路

利用完全二叉树的性质:完全二叉树的每一层(除了可能的最后一层)都是完全填充的。这意味着在深度dd处,节点的数量最多是2d12^{d-1}

首先,读取完全二叉树的节点数nn。定义几个变量,包括当前深度dd、当前层的权值之和sumsum、最大权值之和wmaxwmax以及对应的最大深度dmaxdmax

接着,开始遍历完全二叉树的每一层。每一层的节点数是2d12^{d-1},其中dd是当前深度。然后,读取每个节点的权值,累加到当前层的权值之和sumsum中。

在遍历完一层后,比较当前层的权值之和sumsum与最大权值之和wmaxwmax,如果sumsum更大,则更新最大权值之和wmaxwmax和对应的最大深度dmaxdmax

最后,将最大深度dmaxdmax输出。

注意

完全二叉树不一定是满二叉树,最后一层不一定是完全填充的。所以最后一层的节点的数量可能不是2d12^{d-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;
}