Description
Om Nom is the main character of a game “Cut the Rope”. He is a bright little monster who likes visiting friends living at the other side of the park. However the dark old parks can scare even somebody as fearless as Om Nom, so he asks you to help him.
The park consists of 2n + 1 - 1 squares connected by roads so that the scheme of the park is a full binary tree of depth n. More formally, the entrance to the park is located at the square 1. The exits out of the park are located at squares 2n, 2n + 1, …, 2n + 1 - 1 and these exits lead straight to the Om Nom friends’ houses. From each square i (2 ≤ i < 2n + 1) there is a road to the square . Thus, it is possible to go from the park entrance to each of the exits by walking along exactly n roads.
To light the path roads in the evening, the park keeper installed street lights along each road. The road that leads from square i to square has ai lights.
Om Nom loves counting lights on the way to his friend. Om Nom is afraid of spiders who live in the park, so he doesn’t like to walk along roads that are not enough lit. What he wants is that the way to any of his friends should have in total the same number of lights. That will make him feel safe.
He asked you to help him install additional lights. Determine what minimum number of lights it is needed to additionally place on the park roads so that a path from the entrance to any exit of the park contains the same number of street lights. You may add an arbitrary number of street lights to each of the roads.
Input
The first line contains integer n (1 ≤ n ≤ 10) — the number of roads on the path from the entrance to any exit.
The next line contains 2n + 1 - 2 numbers a2, a3, … a2n + 1 - 1 — the initial numbers of street lights on each road of the park. Here ai is the number of street lights on the road between squares i and . All numbers ai are positive integers, not exceeding 100.
Output
Print the minimum number of street lights that we should add to the roads of the park to make Om Nom feel safe.
Sample test(s)
input
2
1 2 3 4 5 6output
5
Note
Picture for the sample test. Green color denotes the additional street lights.
Standard Report
We use greedy and recursion to solve this task. For each tree rooted at v, we adjust its two subtrees at first, using recursion. Then we increase one edge from v’s child to v.
My Problem Report
这道题是一颗满二叉树,题目要求使根节点到最底层节点的每一条路径的权值都相同时,所需添加在任意边上的最小权值总和。
满二叉树的性质在算法导论上关于二叉堆的章节中有详细阐述。我在思考这种题的时候是受了算导上利用一维数组来静态储存二叉树的启发(这道题中也有足够的提示了)。
首先我们从局部开始思考,对于某个节点,我们可以将它视作一个根节点,那么它通向左边任意一个最底层节点路径的边权必须与右边相同,因为我们无法修改通过比它更高的边来达到这个条件。
那么,对于一个节点,如果说它的左孩子和右孩子都已经完成了修改,我们可以将它的左子树和右子树分别当作一个结点来看待,当前我们就只需使该父亲节点左边权和右边权相等。同理如果我们要是总的修改最少的话,也只需修改max(left,right)-min(left,right)次。
因此我们得出一个结论:当更矮的边完成修改时,我们才能修改更高的边。于是结合满二叉树的构造性质,很容易可以想到反过来遍历一次我们储存二叉树的数组。所以这个算法的效率是 O(n) 。
Source Code
// Created by Chlerry in 2015.
// Copyright (c) 2015 Chlerry. All rights reserved.
// http://codeforces.com/problemset/problem/526/B
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
#include <cmath>
#include <map>
using namespace std;
int h,n;
long long a[10000],ans;
long long Max(long long x,long long y)
{
return x>y?x:y;
}
int main()
{
//freopen("in2.txt","r",stdin);
cin>>h;
n=(2<<h)-1;
for(int i=2;i<=n;i++)
cin>>a[i];
for(int i=n;i>0;i--)
{
long long temp=Max(a[i*2],a[i*2+1]);
a[i]+=temp;
ans+=temp*2-a[i*2]-a[i*2+1];
}
cout<<ans<<endl;
return 0;
}