給出一棵二分搜索樹,再給一個(gè)節(jié)點(diǎn)編號(hào)n,求以這個(gè)節(jié)點(diǎn)為根節(jié)點(diǎn)的子樹葉子節(jié)點(diǎn)的最大值與最小值。若n是奇數(shù),那么他必然是個(gè)葉子節(jié)點(diǎn),最大最小都是他自己。否則求n所在的層數(shù),他的層數(shù)就是他的因子中2的個(gè)數(shù)(規(guī)律),轉(zhuǎn)化為求n的因子中2的個(gè)數(shù)。而2的個(gè)數(shù)取決于n的二進(jìn)制表示中最后一個(gè)1所處的位置i,因?yàn)橹暗哪硯讉€(gè)1,假設(shè)處于j(j>i),那么n可以表示為2^j+2^i+2^x(x>i且個(gè)數(shù)未定)=2^i*(1+2^(j-i)+2^(x-i)),看見米有,n必須有i個(gè)因子2.求出i的值后,即層數(shù),可得n的左右各有num=2^i-1個(gè)兒孫(女),不信請(qǐng)看圖,概不解釋。那么最小值就是n-num,最大值就是n+num.那馬怎么求num呢,這時(shí)就可以請(qǐng)出神奇的位運(yùn)算了(以速度"嗖嗖嗖"的快而揚(yáng)名ACM界),首先是確定二進(jìn)制n后綴連續(xù)0的個(gè)數(shù),這樣想:怎么取出這i個(gè)0呢?其實(shí)不必考慮這個(gè)掣肘的問題,咱們直接跑到結(jié)果上考慮,就是求2^i-1,你花仙米有,這是個(gè)等差數(shù)列的前n項(xiàng)和:2^0+2^1+2^2+……+2^(i-1).那么這又是個(gè)什么形式呢,這就是二進(jìn)制只有連續(xù)i個(gè)1的(其余都是前導(dǎo)0)數(shù)的十進(jìn)制表示形式,OK,好辦了,利用系統(tǒng)自動(dòng)轉(zhuǎn)換功能,咱們只需把這i個(gè)1羅列出來即可:把n的后i個(gè)0變成1,可采取如下形式n^(n|n-1),稍微解釋下,n|n-1是將后i個(gè)0變成1,把第i+1個(gè)1變成0,然后和n抑或一下,得到什么?哈,就是2^i-1,即i個(gè)1的十進(jìn)制形式,代碼就不放了,上面明白了實(shí)現(xiàn)很簡(jiǎn)單的!
那啥,轉(zhuǎn)載務(wù)必注明:Pzjay原創(chuàng)呃!
本文來自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:http://blog.csdn.net/shifuwawa/archive/2010/01/07/5153446.aspx
以下是我根據(jù)上面的描述寫出來的代碼,一次AC,0MS
#include<iostream>
using namespace std;
int main()
{
int n;
cin>>n;
while(n--)
{
int k;
cin>>k;
if(k%2!=0)
{
cout<<k<<" "<<k<<endl;
continue;
}
int num=k^(k|k-1);
cout<<k-num<<" "<<k+num<<endl;
}
return 0;
}
posted on 2010-08-19 13:13
崔佳星 閱讀(1098)
評(píng)論(0) 編輯 收藏 引用 所屬分類:
POJ