九度OJ 1113 二叉树

来源:互联网 发布:mac xampp设置htdoc 编辑:程序博客网 时间:2024/05/22 10:54
题目描述:

 


    如上所示,由正整数1,2,3……组成了一颗特殊二叉树。我们已知这个二叉树的最后一个结点是n。现在的问题是,结点m所在的子树中一共包括多少个结点。

    比如,n = 12,m = 3那么上图中的结点13,14,15以及后面的结点都是不存在的,结点m所在子树中包括的结点有3,6,7,12,因此结点m的所在子树中共有4个结点。

输入:

    输入数据包括多行,每行给出一组测试数据,包括两个整数m,n (1 <= m <= n <= 1000000000)。最后一组测试数据中包括两个0,表示输入的结束,这组数据不用处理。

输出:

    对于每一组测试数据,输出一行,该行包含一个整数,给出结点m所在子树中包括的结点的数目。

样例输入:
3 120 0
样例输出:
4


本题看似很简单,我一上来根据每个结点 i 的左孩子为 2*i , 右孩子为 2*i + 1 的规律,再利用一个队列的数据结构,每次得到一个结点,把它的左右孩子的编号入队,每次出队,发现如果编号小于等于n, 就计数加1,然后再把左右孩子入队。。

当我高兴地提交时,发现内存超了,,再回过头看题目,发现这里的m,n实在太大了,达到10亿。

改进措施:

用left,right只保留结点孩子的最左边,和最右边的编号,它们之间的个数一定是 num  = num * 2,也就是上一行的2倍。 只要负责将num计数,就可以了。

当right大于n时,只要把最后一行多余的数 加上(即 n - left + 1).


#include <iostream>using namespace std;int main(){int m,n;while(cin>>m>>n){if(m == 0 && n == 0)break;int num = 1;int ans = 1;   //表示m点算一个int left = 2 * m;int right = 2 * m + 1;while(right <= n){num = num * 2;ans += num;left = 2 * left;right = 2 * right + 1; } if(left <= n)ans += n - left + 1;cout<<ans<<endl;}return 0;}



0 0
原创粉丝点击