Codeforces#399 B. Code For 1 二叉树中序遍历的规律

题目链接:http://codeforces.com/problemset/problem/768/B

B. Code For 1 time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output

Jon fought bravely to rescue the wildlings who were attacked by the white-walkers at Hardhome. On his arrival, Sam tells him that he wants to go to Oldtown to train at the Citadel to become a maester, so he can return and take the deceased Aemon’s place as maester of Castle Black. Jon agrees to Sam’s proposal and Sam sets off his journey to the Citadel. However becoming a trainee at the Citadel is not a cakewalk and hence the maesters at the Citadel gave Sam a problem to test his eligibility.

Initially Sam has a list with a single element n. Then he has to perform certain operations on this list. In each operation Sam must remove any element x, such that x > 1, from the list and insert at the same position 《Codeforces#399 B. Code For 1 二叉树中序遍历的规律》《Codeforces#399 B. Code For 1 二叉树中序遍历的规律》《Codeforces#399 B. Code For 1 二叉树中序遍历的规律》 sequentially. He must continue with these operations until all the elements in the list are either 0 or 1.

Now the masters want the total number of 1s in the range l to r (1-indexed). Sam wants to become a maester but unfortunately he cannot solve this problem. Can you help Sam to pass the eligibility test?

Input

The first line contains three integers nlr (0 ≤ n < 2500 ≤ r - l ≤ 105r ≥ 1l ≥ 1) – initial element and the range l to r.

It is guaranteed that r is not greater than the length of the final list.

Output

Output the total number of 1s in the range l to r in the final sequence.

Examples input

7 2 5

output

4

input

10 3 10

output

5

Note

Consider first example:

《Codeforces#399 B. Code For 1 二叉树中序遍历的规律》

Elements on positions from 2-nd to 5-th in list is [1, 1, 1, 1]. The number of ones is 4.

For the second example:

《Codeforces#399 B. Code For 1 二叉树中序遍历的规律》

Elements on positions from 3-rd to 10-th in list is [1, 1, 1, 0, 1, 0, 1, 0]. The number of ones is 5.

【分析】:

方法1 :

不难发现,这个分裂过程是一个二叉树,最后的序列就是中序遍历序列。

所以可以模拟二叉树中序遍历,但是树太深复杂度太高。

然而,这棵二叉树每次分裂都是对称的,所以可以用map映射子树,相同的子树就不用再访问了。


方法2:

通过这道题学到了二叉树中序遍历的一个规律。

画一棵二叉树,然后按中序遍历给每个节点标号。

会惊奇的发现,叶子节点那一层全是奇数(即1的倍数)

从下数第二层全是2的倍数

从下数第三层全是4的倍数。。。。

(这一步可以通过位运算 i&-i 直接得出编号i属于哪一层,例如i=12,i&-i = 4,即i在从下数第log2(4)+1层)

即,通过中序遍历的编号就能知道此节点在哪一层,从而知道此处是0还是1,累加进答案即可。


由于本题声明 r-l 不会超过1e5,所以方法2才可行!for(l -> r)

【代码-方法1】:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
map<ll,ll>M;
ll get1(ll x)//求得以x为根的二叉树有多少个1
{
    ll res=0;
    for(int i=0;x;i++){
        if(x%2)res+=(1ll<<i);
        x>>=1;
    }
    return res;
}
ll dfs(ll n,ll &r,ll &ans)//二叉树中序遍历
{
    int k=log2(n);//求得n的二进制数长度-1
    if(r>(1ll<<k)-1)//左子树全部包含在内,无需遍历
    {
        ans+=M[n/2];
        r-=(1ll<<k)-1;
    }
    else if(r>0&&n>1)
        dfs(n/2,r,ans);
    if(r>0){
        ans+=n%2;
        r--;
    }
    if(r>(1ll<<k)-1)//右子树全部包含在内,无需遍历
    {
        ans+=M[n/2];
        r-=(1ll<<k)-1;
    }
    else if(r>0&&n>1)
        dfs(n/2,r,ans);
}
int main()
{
    ll n,l,r,y;
    while(cin>>n>>l>>r)
    {
        M.clear();
        for(ll t=n;t;t>>=1)//预处理每个状态的子树中1的数量
            M[t]=get1(t);
        ll ans1=0,ans2=0;
        dfs(n,r,ans1);
        dfs(n,--l,ans2);
        cout<<ans1-ans2<<endl;
    }
}

【代码-方法2】:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
vector<int>v;
int main()
{
    ll n,l,r;
    while(~scanf("%lld",&n)){
        v.clear();
        scanf("%lld%lld",&l,&r);
        if(n==0){
            puts("0");continue;
        }
        ll ceng=log2(n),ans=0;
        while(n){
            v.push_back(n%2);//每一层的值
            n/=2;
        }
        for(ll i=l;i<=r;++i){
            ans+=v[ceng-log2(i&-i)];//每一项的层数
        }
        cout<<ans<<endl;
    }
    return 0;
}

    原文作者:B树
    原文地址: https://blog.csdn.net/winter2121/article/details/78697805
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注