14th GDCPC J. Just another binary tree

J. Just Another Binary Tree

Input file: stdin    Output file: stdout

Description

Mike is familiar with binary tree.

Mike likes to store binary trees into an array, from 1 to n, which means

1. 1 is the root of the tree

2.  i's left child is 2i

3. i's right child is 2i+1

Mike is not satisfied with this, he wants to know the inorder(中序)traversal of the tree.

For example, n=9, the inorder traversal is " 8 4 9 2 5 14 6 3 7 ".

Mike only wants to know what the x-th number of inorder traversal is.

The inorder traversal index begins from 1, which means if n=8, x=1, the answer is 8.

Mike thinks it's too slow to calculate the whole inorder traversal, and he needs your help.

Input

The first line contains an interger T (T<=100) denoting the number of test cases.

In the following T lines, each line contains a case. In each case, there is 2 intergers x, n ( 1 <= x <= n <= 1e9 ).

You need to ouput the x-th number in the inorder traversal of a binary tree with size n.

Output

For each case, output Case #t: , to represent that this is the t-th case. And then output the answer.

Sample Input

5

100 10

100 10

100 30

100 40

100 50

Sample Output

Case #1: 34

Case #2: 18

Case #3: 39

Case #4: 10

Case #5: 44

题意

一颗 n 个结点的完全二叉树,从根从1开始编号,中序遍历它,问第 x 个遍历到的结点的编号

Source Code

#include <stdio.h>

/* 只用来算2的幂 */
int fast_pow ( int index )
{
	int ans = 1,base = 2;
	while( index > 0 )
	{
		if( index & 1 )
		  ans *= base;
		base *= base;
		index >>= 1;
	}
	return ans;
}

int find ( int x, int n, int depth, int root )
{
	int left,right,nodeNum;
	//int lack;
	/*
	** 先把它当成一颗满二叉树
	** left和right暂时表示这棵树叶子数的一半(分开两半)
	** nodeNum-1 暂时表示整颗满二叉树的全部结点数
	** nodeNum-1-n 算出缺了多少个结点(原先用lack变量来装)
	*/
	left = right = ( nodeNum = fast_pow( depth ) ) >> 2;
	//lack = nodeNum - 1 - n;
	//right -= lack;
	/* 完全二叉树缺结点从右边缺起,所以让right-lack */
	right -= nodeNum - 1 - n;
	/* 右边不够减就左边补上 */
	if( right < 0 )
	{
		left += right;
		right = 0;
	}
	/*
	** 这时nodeNum表示这棵树除去根层和叶子层的部分
	** 劈开两半成两个三角型,其中一个三角的结点数
	*/
	nodeNum = fast_pow( depth - 2 ) - 1;
	/* left和ritht加上nodeNum算出左右子树的结点数 */
	left += nodeNum;
	right += nodeNum;
	/* 中序遍历总是遍历完左子树,再到根,再到右子树 */
	if( x == left + 1 )
	  return root;
	else if( x < left + 1 )
	  return find( x, left, depth-1, root*2 );
	else
	  return find( x-left-1, right, depth-1, root*2+1 );
}

int main()
{
	int iTom,kase;
	scanf("%d",&iTom);
	for( kase = 1; kase <= iTom; kase++ )
	{
		int n,x,depth;
		long long biPow;
		scanf( "%d%d", &n, &x );
		for( biPow=1,depth=0; biPow < n+1; biPow <<= 1,depth++ );
		printf( "Case #%d: %d\n", kase, find( x, n, depth, 1 ) );
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值