poj 2309 BST (^ ^)

这是个很好的题目呢~~画图画了半天 = =、、

 

这是一棵完全二叉查找树 = =。。。

 

给你一个节点n,求n的子树中最小,最大值。

 

放图,得睡了,明天继续写。

 

 

 

继续~

 

 

看下面的图,找规律。可以发现。每个节点的父节点的父节点的。。。总之,总有一个是2的幂次。等于说,这些所有的除了2的幂次的数,都是2幂次数的右子树上的一个节点。而且可以发现,奇数都是叶节点,而且所有的叶节点都是奇数。

我的想法就是,给你一个数n,找比n小的最近的2的幂次的数为root,如果n本身就是2的幂次,它自己就是root。然后开始从root往下找,找到与n相等的地方,比如查找28,先找到16,是2^4,count = 4-1 = 3。那么16就需要增加2^(count-1)去寻找。如果16+(2^(count-1)) > n 就16+ (2^(count-1)) ,反之,16-(2^(count-1)) ,就是查找到n。count每次减1,直到找到n。

 

root = 2^4 = 16;

比如  root + 8 < 28,  root = 16+8 = 24;

root + 4 == 28;找到n跳出。

然后根据得到的count继续忘下找,相当于找到28忘子节点需要加或者减的数。然后一直找到count 为0。

 

 

 

poj 2309 BST (^ ^)_第1张图片

 

 

 

#include <stdio.h> #include <string.h> #include <iostream> #include <stdlib.h> using namespace std; int main() { int ncases,n,i; scanf("%d",&ncases); while( ncases-- ) { scanf("%d",&n); if( n%2 == 1 ) { printf("%d %d/n",n,n);//经画图,以及种种考虑 = =。。。奇数全在最后一行 continue; } int tmp = n,count = 0; while( tmp != 0 ) //查找比n小的最近的2^n的数 { tmp /= 2; count++; } count -- ; int flag = 0; if( (1<<count) == n ) // 如果本身就是2的幂次,就标记下~下面有用。。 flag = 1; int root = (1 << count); //就是这个root啦~~ for(i=count-1; i>=0; i--) // 从root开始往下查找。经种种现象表示,n一定是比它小的它最近的2的幂次的数的子节点。 { if( n > root ) root += (1<<i); if( n == root ) break; if( n < root ) root -= (1<<i); } if( flag == 1 ) // 如果本身就是2的幂次,那么少加一次。。 i++; int min,max; min = max = n; for(int k=i-1; k>=0; k--) // 作为根节点,往左子树左边和右子树右边找最小和最大值。 { min -= (1<<k); max += (1<<k); } printf("%d %d/n",min,max); } return 0; }  

你可能感兴趣的:(poj 2309 BST (^ ^))