Codeforces 1237 E Balanced Binary Search Trees —— 构造类似完全二叉树

This way

题意:

现在有1-n这么多点,你要用这些点构成一个二叉树,使得这个二叉树满足以下条件:
1.任意一个节点与其右儿子的奇偶性相同
2.任意一个节点与其左儿子的奇偶性相反
3.所有节点的深度加起来最小

题解:

这道题真的是让我大吃一斤。有很多的解法啊,但是很明显我是去看最简单的那种,然后我就懵逼了半天,不知所措。
首先深度之和最小的意思就是类似一个完全二叉树,叶子结点的深度差不超过1.
然后它的模数是骗人的,总共只有两种可能,要么是0,要么是1,因为他有一定的构成方法,不会出现第二种可能(为什么,我也不是很懂)
首先n=1的时候就是1个点。
n=2的时候就是1是2的左二子
n=3的时候不可能。
n=4的时候是样例
然后有一些很重要的性质去发现:
首先n一定是在最右下角。因为它是最大的,然后n与根节点的奇偶性相同,那么根节点右子树的大小一定是偶数的。
那么对于n=5的时候,很明显不能在右子树上加东西,因为那样会破坏平衡,如果根节点变动的话,右子树就至少变成4,那么这棵树又不平衡了。所以只能往最左下角加一个点,使这棵树平衡(也就是将所有点的值+1,再往左下角加一个点)。但是这种方法对于6的时候不行了,因为没有位置可以给你去放,增加一个点的同时势必还要增加一个点,这样就不满足了:
在这里插入图片描述
比如你增加一个红色的,那么就一定要增加一个黄色的,因为同奇偶的约束。
这样的话就不满足深度之和最小这个条件。如果要满足这个条件,那么就必须在右边也加上两个点。
那么我们就可以发现一个规律:
两个相同深度的平衡的树可以连起来,比如4,就是1和2相连。9就是4和4相连。
但是如果这棵树是奇数的,就必须在左下角添加一个节点才能连上去,因为右子树必须是偶数的。
那么就得出了现在的程序:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    scanf("%d",&n);
    int now=1;
    while(now+1<n){
        if(now&1)
            now=(now)+(1)+(now+1);
        else
            now=(now)+(1)+(now);
    }
    if(now==n||now+1==n)
        printf("1\n");
    else
        printf("0\n");
    return 0;
}

发布了530 篇原创文章 · 获赞 31 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/tianyizhicheng/article/details/104232227