poj百炼 2788

来源:互联网 发布:新加坡 一带一路 知乎 编辑:程序博客网 时间:2024/04/30 04:41

总时间限制:

3000ms
内存限制:
65536kB
描述


如上图所示,由正整数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所在子树中包括的结点的数目

分析:

这题目不需要用二叉树建立,查找然后计数,如果这样的话,你一定会超时。
这道题主要是用二叉树的性质来做:
如上图:leftchild->data=2*parent->data right->data=2*parent->data+1;
然后这样做:
#include<stdio.h>
int i=0,count=1;
intx(int n,int m,int*k)
{   
  while(n<m){      
        if((n*=2)<=m)              
  count++;            
   if((n+1)<=m)            
   {               
     count++;              
      k[i++];             
  }       
   }         
return count;
}intmain()
{   
int n,m,count1; 
   int k[100],z;   
while(scanf("%d%d",&n,&m),n) 
   {      
 count1=x(n,m,k);     
   for(z=0;z<i;z++)        
    count1=x(k[z],m,k); 
   }
 printf("%d",count1);
}

如果你这样的话,也是徒劳。虽然答案没错,但是超时了。所以这道题不能用递归。

然后看了别人的结题报告,才发现上述问题。

#include<stdio.h>

int main()
{
 int M,N;
 while(scanf("%d%d",&M,&N)&&M&&N)
 {
  if(M>N)
  {
   printf("0\n");
   continue;
  }
  else
  {
   int ret=1;
   int curlevelmin=M,curlevelmax=M;
   int nextlevelmin,nextlevelmax;

   while(1)
   {
    nextlevelmin=2*curlevelmin;//给左右子赋值
    nextlevelmax=2*curlevelmax+1;

    if(nextlevelmax<=N)
    {
     ret+=(nextlevelmax-nextlevelmin+1);如果满足右子小于N,则加上该层节点数
     if(nextlevelmax==N)  如果正好是右子的话,直接推出并输出。
      break;
    }
    else if(nextlevelmin<=N)如果右子大而左子小
    {
     ret+=(N-nextlevelmin+1);
     break;
    }
    else
     break;

    curlevelmin=nextlevelmin;
    curlevelmax=nextlevelmax;
   }
   printf("%d\n",ret);
  }
 }

 return 0;
}

 

0 0
原创粉丝点击