堆 (heap)解題報告

堆 (heap)

Description

給你一棵有n層的滿二叉樹,要求父親的權值大於等於兒子的權值,並且左子樹的任意一個結點的權值都小於等於右子樹任意一個節點的權值。

但是這棵二叉樹可能不滿足這個條件,現在你需要對若干結點的權值進行調整使得它滿足這個條件;並且你希望調整的節點最少。

Input

第一行一個正整數n。

接下來有n行,第n行有2^(i-1)個正整數,依次表示從左向右第i 層的節點的權值(≤10^9)。

Output

一行一個非負整數,表示最少需要調整的節點的數量。

Sample Input 1 

2 
2 
1 3 

Sample Output 1

1 

Sample Input 2 

3
70010496 
168640497 626338106 
713289764 305468210 123552884 893428251 

Sample Output 2

5

Hint

樣例解釋 :

我們可以把3調整爲1或2,或者把2調整爲任意一個大於等於3的數。

數據範圍 :

1.JPG

考慮數的後序遍歷,答案等於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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章