山東省第五屆ACM大學生程式設計競賽-Full Binary Tree(二叉樹&&求任意兩節點路徑)

kewlgrl發表於2016-04-20

Full Binary Tree

Time Limit: 2000ms   Memory limit: 65536K  有疑問?點這裡^_^

題目描述

In computer science, a binary tree is a tree data structure in which each node has at most two children. Consider an infinite full binary tree (each node has two children except the leaf nodes) defined as follows. For a node labelled v its left child will be labelled 2 * v and its right child will be labelled 2 * v + 1. The root is labelled as 1.
 
You are given n queries of the form i, j. For each query, you have to print the length of the shortest path between node labelled i and node labelled j.
 

輸入

First line contains n(1 ≤ n ≤ 10^5), the number of queries. Each query consists of two space separated integers i and j(1 ≤ i, j ≤ 10^9) in one line.
 

輸出

For each query, print the required answer in one line.
 

示例輸入

5
1 2
2 3
4 3
1024 2048
3214567 9998877

示例輸出

1
2
3
1
44

提示

 

來源

2014年山東省第五屆ACM大學生程式設計競賽


題目意思:

有一棵滿二叉樹,形狀如圖:

根節點為1,節點數值最大不超過10e9。

求任意兩個節點a和b之間的最短路徑。


解題思路:

①求出較小節點所在的層數;

②使較大節點向上跳到較小節點所在的層數,每跳一次路徑加1;

③此時兩節點在同一層,同時向上跳直到a=b,每個節點每跳一次路徑加1,則兩節點一起跳路徑加2;

④此時得到的路徑長度就是a和b之間的最短路徑。


AC程式碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int p[31];//2^30>N
const long long N=1000000010;
void f()
{
    int i;
    for(i=0; pow(2,i)<=N; ++i)
        p[i]=pow(2,i);//p[]儲存2^i
}

int main()
{
    int t;
    f();
    scanf("%d",&t);
    while(t--)
    {
        int a,b;
         scanf("%d%d",&a,&b);
        if(a>b) swap(a,b);//令a始終小於等於b
        int ans=0;
        int pos;//較小的數a的層數為pos
        for(int i=0; i<31; i++)
            if(a>=p[i]&&a<p[i+1])
            {
                pos=i;
                break;
            }
        while(1)//改變b的層數使a和b在同一層上
        {
            if(b>=p[pos]&&b<p[pos+1])
                break;
            b/=2;
            ans++;//每跳一層路徑加一
        }

        while(a!=b)//兩個節點一起跳
        {
            a/=2;
            b/=2;
            ans+=2;//每個節點跳一次路徑加1,兩個節點同時跳就是加2
        }
        printf("%d\n",ans);
    }
    return 0;
}


相關文章