大家都已经放假了,大概没几个人还在考试状态的了,还剩下一科数据结构,好烦啊,所以就来AcWing刷题了hhh,事实证明,还是刷题有意思,写写题解减减压吧。
题目链接: AcWing 1240 完全二叉树的权值
题意: 给定一个序列,这个序列代表的是一棵完全二叉树的结点权值,而且是按照层序来给的,计算每一层权值之和,输出权值最大的层的深度,如果有最大值有多个,那就输出深度最小的
解题思路:
这道题给的输入非常友好,已经说清楚了给的就是一棵完全二叉树,根据完全二叉树的性质,第$i$层有$2^{i-1}$个结点,所以就可以用两层循环计算每一层的结点权值。外层循环控制层,内层循环控制每层的结点个数
注意事项:
- 深度是从$1$开始的,题目中有说,但是写代码的时候要留意一下
- 计算深度可以用库函数
log()
,但是这个默认是以$10$为底的,需要用换底公式进行处理,即$log_ab=\frac {log_cb}{log_ca}\qquad$
代码如下:
#include <cmath>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
typedef long long LL; //有可能会爆int
int n, a[N];
LL res, maxa = -0x3f3f3f3f;
int main() {
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", a + i);
}
// k 是每层的结点个数,每一次迭代是翻倍
for (int i = 0, k = 1; i < n; i += k, k *= 2) {
LL cnt = 0;
// 因为完全二叉树最后一层有可能不是满的,所以要加上一个条件 i+j<n ,保证不会超过结点个数
for (int j = 0; i + j < n && j < k; j++) {
cnt += a[j + i];
}
if (cnt > maxa) {
maxa = cnt;
res = log(k) / log(2) + 1;
}
}
printf("%lld\n", res);
return 0;
}