注册 登录
编程论坛 C语言论坛

哥哥们,姐姐们,救救小弟吧,这是今年蓝桥杯原题

青铜小弟 发布于 2019-06-18 21:39, 1875 次点击
给定一棵包含 N 个节点的完全二叉树,树上每个节点都有一个权值,按从
上到下、从左到右的顺序依次是 A 1 , A 2 , ··· A N
现在小明要把相同深度的节点的权值加在一起,他想知道哪个深度的节点
权值之和最大?如果有多个深度的权值和同为最大,请你输出其中最小的深度。
注:根的深度是 1。
【输入格式】
第一行包含一个整数 N。
第二行包含 N 个整数 A 1 , A 2 , ··· A N 。
【输出格式】
输出一个整数代表答案。
【样例输入】
7
1 6 5 4 3 2 1
【评测用例规模与约定】
对于所有评测用例,1 ≤ N ≤ 100000,−100000 ≤ A i ≤ 100000。
3 回复
#2
rjsp2019-06-19 09:42
没有任何需要想一想的地方吧

首先,题目说“1≤N≤100000”,那么可以算出最多17层,第16层最多有32768个节点,第17层最多有34465个节点(不加限定的话第17层可以有65536个节点,但这样一来总节点数就131071个了)。
题目又说“−100000≤Ai≤100000”,那么 34465*100000 = 0xCD6D6AA0; 同层的节点权值之和范围是[-0xCD6D6AA0,+0xCD6D6AA0],因此四字节的具符号整型是存不下它的
看到这里心一沉,如果评测用例没超过四字节的具符号整型,那么看出应当用long long的人反而就吃亏了。

程序代码:
#include <stdio.h>

long long foo( unsigned count )
{
    long long r = 0;
    for( unsigned i=0; i!=count; ++i )
    {
        long a;
        scanf( "%ld", &a );
        r += a;
    }
    return r;
}

int main( void )
{
    unsigned long n;
    scanf( "%u", &n );

    unsigned layer = 0;
    long long weight = 0;
    for( unsigned i=0; n!=0; ++i )
    {
        unsigned count = (1u<<i)<=n ? (1u<<i) : n;
        long long t = foo( count );
        n -= count;

        if( weight < t )
        {
            weight = t;
            layer = i;
        }
    }
    printf( "%u\n", layer+1 );
}

#3
青铜小弟2019-06-19 20:38
回复 2楼 rjsp
您能解释一下这个程序吗?我是一个新手,谢谢,麻烦您下了!
#4
rjsp2019-06-21 10:33
回复 3楼 青铜小弟
这有什么不能理解的?
第一层1个,加起来
第二层2个,加起来
第三层4个,加起来
第四层8个,加起来
……
哪层累积和最大就取哪层。
1