平衡二叉树 (牛客国庆day2)解锁二叉树打表姿势&&找规律套路

时间:2021-09-04 12:01:01

链接:https://www.nowcoder.com/acm/contest/202/F
来源:牛客网

平衡二叉树,顾名思义就是一棵“平衡”的二叉树。在这道题中,“平衡”的定义为,对于树中任意一个节点,都满足左右子树的高度差不超过 d. 空树的高度定义为0,单个节点的高度为1,其他情况下树的高度定义为根节点左右子树高度最大值 + 1. 一棵在高度上平衡的树,节点数可能不平衡,因此再定义一棵树的不平衡度为这棵树中所有节点的左右子树的节点数之差的最大值。
给定平衡的定义参数d, 你需要求出所有高度为 n 的平衡树中不平衡度的最大值。
链接:https://www.nowcoder.com/acm/contest/202/F
来源:牛客网

输入描述:

两个整数,n, d.

输出描述:

一个整数:所有高度为 n 的平衡树中不平衡度的最大值。

输入例子:
4 1
输出例子:
5

-->

示例1

输入

复制

4 1

输出

复制

5

说明

下面这棵树在 d=1 的定义下高度是平衡的,其不平衡度为 5。
平衡二叉树 (牛客国庆day2)解锁二叉树打表姿势&&找规律套路

备注:

0≤ m ≤ n ≤ 60

很容易想到思路从根节点开始一边为满二叉树,另外一边为满足题目平衡条件的树的最少节点数
我和队友手推的这一题结果手算出表了但是规律找不到 难受的一批 经验严重不足 然后仔细看可以慢慢看出规律 ans表示
另外一边为满足题目平衡条件的树的最少节点数
然后仔细观察可以看到这个
ans[i] = ans[i-1] + ans[i - d - 1] + 1
附上打表代码
 int d, sum;
struct node {
int num;
node *lson, *rson;
node () {
num = ;
lson = rson = NULL;
}
};
void del ( node* root ) {
if ( !root ) return ;
del ( root->lson );
del ( root->rson );
delete ( root );
}
int dfs ( int dep, node* root ) {
if ( dep <= ) return ;
root->lson = new node();
root->num += dfs ( dep - , root->lson );
sum++;
if ( root->num - > d ) {
root->rson = new node();
dfs ( root->num - - d, root->rson );
}
return root->num;
}
int main() {
for ( int n = ; n <= ; n++ ) {
d = , sum = ;
node* root = new node();
dfs ( n - - d, root );
printf ( "n=%d sum=%d\n", n, sum );
del ( root );
}
return ;
}

正解代码

 #include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#include <algorithm>
#include <set>
#include <iostream>
#include <map>
#include <stack>
#include <string>
#include <vector>
#define pi acos(-1.0)
#define eps 1e-6
#define fi first
#define se second
#define rtl rt<<1
#define rtr rt<<1|1
#define bug printf("******\n")
#define mem(a,b) memset(a,b,sizeof(a))
#define name2str(x) #x
#define fuck(x) cout<<#x" = "<<x<<endl
#define f(a) a*a
#define sf(n) scanf("%d", &n)
#define sff(a,b) scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define sffff(a,b,c,d) scanf("%d %d %d %d", &a, &b, &c, &d)
#define pf printf
#define FRE(i,a,b) for(i = a; i <= b; i++)
#define FREE(i,a,b) for(i = a; i >= b; i--)
#define FRL(i,a,b) for(i = a; i < b; i++)+
#define FRLL(i,a,b) for(i = a; i > b; i--)
#define FIN freopen("in.txt","r",stdin)
#define gcd(a,b) __gcd(a,b)
#define lowbit(x) x&-x
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int mod = 1e9 + ;
const int maxn = 1e5 + ;
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
int n, d;
LL ans[];
LL expmod ( LL a, LL b ) {
LL ret = ;
while ( b ) {
if ( b & ) ret = ret * a;
a = a * a;
b = b >> ;
}
return ret;
}
int main() {
while ( ~sff ( n, d ) ) {
mem ( ans, );
for ( int i = d + ; i <= * d + ; i++ ) ans[i] = i - d - ;
for ( int i = * d + ; i <= n ; i++ ) ans[i] = ans[i-] + ans[i - d - ] + ;
// fuck(ans[n]);
printf ( "%lld\n", expmod ( , n - ) - - ans[n] );
}
return ;
}