题目链接Subtrees
题意:给出一个完全二叉树的节点数,求其不同节点数的子树的个数
思路:
1、先考虑是否为满二叉树,如果是满二叉树,那么不同节点子树的个数即为该而二叉树的层数
2、如果不为满二叉树,那么就寻找该二叉树的最大满二叉树,记录这个层数最大的满二叉树的层数,那么剩下的子树就是小于最大层数的满二叉树
这时候就只需要去重,还有一部分子树是非完全二叉树,那么就看以该节点为根节点的二叉树是否为非满完全二叉树,如果是,就+1,并继续向下寻找,直至叶子节点,因为每一层的非满完全二叉树的节点数肯定不同
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
using namespace std;
typedef long long ll;
ll ans,n;
int maxn;
int my_max(int a,int b)
{
if(a < b){
return b;
}
return a;
}
void Find(ll x)
{
ll l = x,r = x;
int dep = 1;
//寻找最左端的叶节点
while(2 * l <= n){
l *= 2;
dep++;
}
//寻找最右端的叶节点
while(2 * r + 1 <= n){
r = 2 * r + 1;
}
//这里如果l <= r 即表示以x节点为根节点的
//树为满二叉树,即只需要比较层数即可
//所以这里也是去重操作,而且这里到最后到达叶节点后
//作为递归终点,不然会一直递归下去
if(l <= r){
maxn = my_max(dep,maxn);
}
else{
//如果是非满二叉树的完全二叉树
//那么以x为根节点的二叉树的节点数肯定是独一无二的一个
//所以整个完全二叉树不同节点数的子树数量要加1
Find(2 * x);
Find(2 * x + 1);
ans++;
}
}
int main()
{
while(cin>>n){
ans = 0;
maxn = 0;
Find(1);
cout<<ans + maxn<<endl;
}
return 0;
}