山东省第五届省赛 F - Full Binary Tree (利用满二叉树性质的一个思维题)

Description
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.

Input
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.

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

Sample Input
5
1 2
2 3
4 3
1024 2048
3214567 9998877
Sample Output
1
2
3
1
44

**【题意】:**给你T组a,b然后让你利用二叉树的性质求出两者之间的最短距离,其实也就是变向去找他们最近的共同的父亲节点。

**【思路】:**这个题的思路很好想,你可以先把一个节点b的所以父亲节点存下来并且把它经过的步数也存下来所以这里需要一个结构体。par【】 然后在遍历另一个节点a如果找到了共同的父亲节点,则跳出循环并把两者的步数相加则为最短路径,如果该节点a大于par【】,则让a变为a的父亲节点,如果a小于par【】,则让par【】变为其父亲节点。
具体看下面代码及其注释。
由满二叉树性质可知他们一定存在相同父亲节点,因为最后只有一个根节点。
这个方法好想是好想但是时间复杂度太高,连memset也卡了,去掉它才勉勉强强过的。

【代码】:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
using namespace std;
const int N=5e5+10;
struct F
{
    int son;//每一步的父亲节点
    int tmp;//步数
} par[N];  //用来存父亲节点 还有经过的步数

int main()
{
    ios::sync_with_stdio(false);
    int T;
    cin>>T;
    while(T--)
    {
        int a,b;
        cin>>a>>b;
        int t=1;
        par[1].son=b;//初始化最开始的为b本身
        par[1].tmp=0;//此时的步数为0
        while(b!=1)//不断寻找b的父亲节点 直到为根节点1
        {
            t++;
            b/=2;//满二叉树性质 x/2 为x的父亲节点
            par[t].son=b;//记录父亲节点
            par[t].tmp=par[t-1].tmp+1;//步数加1
        }
        t=1;//初始化t 
        int ans=0;
        while(1)
        {
            if(par[t].son==a)
                break;
            else if(par[t].son<a) //说明a大 则将a变为其父亲节点 并步数加1
            {
                ans++;
                a/=2;
            }
            else //a小 则说明在同一层,且a在par左边 所以将par变为父亲节点
                t++;
        }
        cout<<ans+par[t].tmp<<endl;//最短距离=两者到公共父亲节点的距离之和
    }
    return 0;
}
    原文作者:满二叉树
    原文地址: https://blog.csdn.net/Puppet__/article/details/79129148
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞