1950F - 0, 1, 2, Tree!

题目链接:0, 1, 2, Tree!

本道题目其实就是一道贪心的题目,对于思维的考察较多。

思路:

1.首先我们想想什么情况下该树不存在?

由二叉树的性质可知每一个子节点个数为2的树都必须有两个,每一个子节点为1的树必须有1个,那么最后的0,也就是叶子节点的数量跟这两个有什么关系?

先看一棵树:

                    O

                /         \

           aO            Oe        假设这么一棵树,我们可以发现a的子节点有两个,那么叶子节点就比

         /     \            |            这个节点多了1,子节点为1的则就只有一个,我们可以把d这个叶子节点

      O        O        O          分给根节点,这样每个子节点个数为2的节点都有2个叶子节点。

     b          c          d          所以可以知道,当叶子节点个数 = 子节点个数为2的节点个数 + 1

2.怎么贪心的去考虑这棵树?

换种问法,如何合理分配这三种节点,首先0肯定是叶子节点,所以不用考虑,那就考虑如何分配这两种节点使树的高度最小?

                           O                                                            O

                        /       \                                                          |

                    O            O                                                     O

                /       \         /      \                                            /         \

              O       O     O       O                                      O            O  

           /     \       |       |                                             /       \        /     \

        O       O    O    O                                          O         O    O       O

                                                                             |

                                                                            O        

从这两棵树中我们可以清晰的发现,要使得高度最小,那肯定是先放子节点个数为2的再去放1的。

那么思路到这边就结束了。

代码如何实现?以及一些细节:

#include <bits/stdc++.h>
#define int long long
using namespace std;
int a,b,c;

void solve(){
    cin>>a>>b>>c;
	if(a+1!=c){
		cout<<-1<<"\n";
		return;
	}
	int h1=0;
	for(int i=1;i<=a;i++){
		if(pow(2,i)-1>a){
			h1=i-1;
			break;
		}
	}
	//cout<<"h1="<<h1<<"\n";

	int less=a-(pow(2,h1)-1);//还有多少个2
	//cout<<"less="<<less<<"\n";
	int cur_less=(pow(2,h1)-less);//目前该行还有多少个1可以填
	//cout<<"cur="<<cur_less<<"\n";
	int p=pow(2,h1)+less;//表示接下来还有多少点
	//cout<<"p="<<p<<"\n";
	
	if(!less&&!b){//如果是满二叉树
		cout<<h1<<"\n";
		return;
	}
	
	if(cur_less>=b){
		h1++;
		cout<<h1<<"\n";
	}
	else{
		b-=cur_less;
		h1++;
		h1+=((b-1)/p+1);
		cout<<h1<<"\n";
	}

}

signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t;cin>>t;
    while(t--){
        solve();
    }

    return 0;
}

  • 27
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值