題目描述
給定一棵包含N 個節點的完全二叉樹,樹上每個節點都有一個權值,按從上到下、從左到右的順序依次是,如下圖所示:
現在小明要把相同深度的節點的權值加在一起,他想知道哪個深度的節點權值之和最大?如果有多個深度的權值和同為最大,請你輸出其中最小的深度。
注:根的深度是 1。
輸入格式
第一行包含一個整數 N。
第二行包含N 個整數 。
輸出格式
輸出一個整數代表答案。
輸入輸出樣例
輸入 #1複製
7
1 6 5 4 3 2 1
輸出 #1複製
2
說明/提示
對於所有評測用例,。
藍橋杯 2019 省賽 A 組 F 題(B 組 G 題)。
題意分析
由完全二叉樹的陣列儲存可知,第一層的元素個數為1個元素,第二層的元素個數為2,第i層的元素為2i 個,故問題轉化為分別統計各層元素的和,同時比較其最大值在第幾層,如果最大值相同求層數最小的哪個層數是多少。
程式碼一
#include<iostream> #include<cmath> using namespace std; int main() { long long ans=-10e10,cur=0;//是到當前位置時的最大值為ans,cur為當前層所有元素之和,注意cur,ans的取值範圍。 int n,b,c=1,sd=1,l=2;//sd為最大值所在的層數,l表示當前是第幾層 b=c=2;//當c計算第i層有幾個元素,b表示當前層已統計了幾個元素。 cin>>n; cin>>ans; for (int i=2;i<=n;i++) { int x; cin>>x; cur+=x; b--; if (b==0||i==n) { if (ans<cur) { ans=cur; sd=l; } l++; c*=2; b=c; cur=0; } } cout<<sd<<endl; }
程式碼二,樹的遍歷法
#include<iostream> using namespace std; const int maxn=1e5+10; int a[maxn],n,dep; long long b[100]; void dfs(int x,int d)//x當前結點編號,d當前結點的深度。 { if (x>n) return ; dep=max(dep,d);//樹的深度 b[d]+=a[x];//同一層的元素的和 dfs(2*x,d+1); dfs(2*x+1,d+1); } int main() { cin>>n; for (int i=1;i<=n;i++) { cin>>a[i]; } dfs(1,1); int ansi=1; for (int i=1;i<=dep;i++)//查詢第一個最大值的位置,思考與dfs是否可以合併 { if (b[ansi]<b[i]) ansi=i; } cout<<ansi<<endl; }
合併一下
#include<iostream> using namespace std; const int maxn=1e5+10; int a[maxn],n,ansi=1; long long b[100]; void dfs(int x,int d) { if (x>n) return ; b[d]+=a[x]; dfs(2*x,d+1); dfs(2*x+1,d+1); if (b[ansi]<b[d]) ansi=d; } int main() { cin>>n; for (int i=1;i<=n;i++) { cin>>a[i]; } dfs(1,1); cout<<ansi<<endl; }