題解:CF1237E Balanced Binary Search Trees

hhhqx發表於2024-12-03

https://www.luogu.com.cn/problem/CF1237E


https://www.luogu.com.cn/article/fd9qi7ie 的一些補充。

step1:容易發現根的奇偶性和 \(n\) 的奇偶性相同。所以根的右子樹大小一定是偶數。

step2:一顆合法的樹,滿足根的左右子樹也是合法的樹。

step3:\(2^k - 1\) 顯然是奇數,所以一顆滿二叉樹(除了只有一個點的樹)一定是不合法的。

step4:一個合法的樹,根的左右子樹也都是合法的樹。

考慮兩個合法的樹合併為一個合法的樹。

題目中要求每個點到根的距離的和最小,也就是樹是一顆滿二叉樹在最後一層刪除一些點得到。所以那兩個合法的樹必須高度相同為 \(i\)(如果不同,第一種情況是其中一棵樹是滿二叉樹,這不合法,第二種情況反之,這樣合併出來的樹不合法)。

\(f_i\) 表示深度為 \(i\) 的合法的樹的最小大小。對於 \(i \le 2\) 先特判掉。

接下來需要證明深度為 \(i(i \ge 3)\) 的合法的數的大小值有且只有可能 \(f_i\)\(f_i+1\)。考慮歸納法證明:

  • 對於 \(i=3\) 成立(暴推驗證)。設根左子樹大小為 \(L\),根右子樹大小為 \(R\)
  • \(R\) 只能是偶數,而 \(L\) 也只能是 \(f_{i-1}\)\(f_{i-1}+1\)

順便也得出了轉移式 \(f_i = 2 \times f_{i-1} + 1 + [f_{i-1} \bmod 2 = 1]\)

#include <bits/stdc++.h>

using namespace std;
using LL = long long;

int n, f[30];

int main(){
	cin >> n;
	if(n == 1 || n == 2 || n == 4 || n == 5){
		cout << 1;
		return 0;
	}else if(n == 3){
		cout << 0;
		return 0;
	}
	f[3] = 4;
	for(int i = 4; i <= 25; i++){
		f[i] = 2 * f[i - 1] + 1 + (f[i - 1] % 2 == 1);
		if(f[i] == n || f[i] + 1 == n){
			cout << 1;
			return 0;
		}
	}
	cout << 0;
	return 0;
}

相關文章