Description
給你一棵有n層的滿二叉樹,要求父親的權值大於等於兒子的權值,並且左子樹的任意一個結點的權值都小於等於右子樹任意一個節點的權值。
但是這棵二叉樹可能不滿足這個條件,現在你需要對若干結點的權值進行調整使得它滿足這個條件;並且你希望調整的節點最少。
Input
第一行一個正整數n。
接下來有n行,第n行有2^(i-1)個正整數,依次表示從左向右第i 層的節點的權值(≤10^9)。
Output
一行一個非負整數,表示最少需要調整的節點的數量。
Hint
樣例解釋 :
我們可以把3調整爲1或2,或者把2調整爲任意一個大於等於3的數。
數據範圍 :
考慮數的後序遍歷,答案等於2^n-1-最長不降子序列長度(各位感性理解一波?!)
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
struct ed{int l,r,c;}tr[10000000];
int n,t,p,a[10000000],f[10000000],dp[10000000];
void build(int x){//建樹
if(x>n) return;
tr[x].c=a[x];
tr[x].l=2*x;tr[x].r=2*x+1;
build(2*x);build(2*x+1);
}
void hdfs(int x){//後序遍歷
if(x<=n){
hdfs(tr[x].l);hdfs(tr[x].r);
f[++t]=tr[x].c;
}
return;
}
int main()
{
scanf("%d",&n);
n=pow(2,n)-1;
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
build(1);hdfs(1);
dp[1]=f[1];p=1;
for (int i=2;i<=n;i++){
if (f[i]>=dp[p]) dp[++p]=f[i];
else {
int j=upper_bound(dp+1,dp+p+1,f[i])-dp;
dp[j]=f[i];
}
}
cout<<n-p;
return 0;
}