【满二叉树 && dp】URAL - 1117 Hierarchy

Step1 Problem:

满二叉树,中序遍历按照1,2,3…给二叉树编号。
x点下一步只能到达 x+1点 或者 x-1点,花费时间为两个点之间路径的节点个数(不包含端点)。
求u点到v点所需时间。
数据范围:0 < u, v<=2^31-1。

Step2 Involving algorithms:

满二叉树 && dp

Step3 Ideas:

满二叉树的形状,左子树和右子树是一样的 且 对称。
我们预处理求出1->1, 1->2, 1->4, 1->8….所需的时间。
1->1 = 0, 因为不动
1->2 = 0, 因为之间路径节点个数为0
1->4 = 1->2 + 2->3 + 1 = 1;(1->2 = 2->3 因为以4为根的子树,它们是对称的。)
1->8 = 1->4 + 4->7 + 2 = 4;
1->16 = 1->8 + 8->15 + 3 = 11;
1->32 = 1->16 + 16->31 + 4 = 26; 以此类推下去。
状态dp[i]:1->(2^i)的时间,dp[i] = dp[i-1]*2+i-1;
假设我们求
1->12 = 1->8 + 8->9 + 1->4。
1->14 = 1->8 + 8->9 + 1->4 + 4->5 + 1->2。

Step4 Code:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll dp[50];
ll solve(ll x)
{
    int i;
    ll res = 0;
    while(1) {
      // cout << res << ' ' << x << endl;
        for(i = 0; ;i++)
        {
            if((1LL<<i) >= x) break;
        }
        if((1LL<<i) == x) {
          return res + dp[i];
        }
        res += dp[i-1] + i-2;
        x -= 1LL<<(i-1);
    }
}
int main()
{
    dp[0] = dp[1] = 0;
    for(int i = 2; i <= 32; i++)//预处理1->(1<<i)所需的时间
    {
        dp[i] = dp[i-1]*2 + (i-1);
       // cout << i << ' ' << dp[i] <<endl;
    }
    //cout << solve(12) << endl;
    ll u, v;
    while(cin >> u >> v)
    {
        if(u > v) swap(u, v);
        cout << solve(v) - solve(u) << endl;
    }
    return 0;
}
    原文作者:满二叉树
    原文地址: https://blog.csdn.net/bbbbswbq/article/details/79747337
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞