HDU 5975 Aninteresting game(树状数组)

原题链接

Problem Description

Let’s play a game.We add numbers 1,2…n in increasing order from 1 and put them into some sets.
When we add i,we must create a new set, and put iinto it.And meanwhile we have to bring [i-lowbit(i)+1,i-1] from their original sets, and put them into the new set,too.When we put one integer into a set,it costs us one unit physical strength. But bringing integer from old set does not cost any physical strength.
After we add 1,2…n,we have q queries now.There are two different kinds of query:
1 L R:query the cost of strength after we add all of [L,R](1≤L≤R≤n)
2 x:query the units of strength we cost for putting x(1≤x≤n) into some sets.

Input

There are several cases,process till end of the input.
For each case,the first line contains two integers n and q.Then q lines follow.Each line contains one query.The form of query has been shown above.
n≤10^18,q≤10^5

Output

For each query, please output one line containing your answer for this query

Sample Input

10 2
1 8 9
2 6

Sample Output

9
2

Hint

lowbit(i) =i&(-i).It means the size of the lowest nonzero bits in binary of i. For example, 610=1102, lowbit(6) =102= 210
When we add 8,we should bring [1,7] and 8 into new set.
When we add 9,we should bring [9,8] (empty) and 9 into new set.
So the first answer is 8+1=9.
When we add 6 and 8,we should put 6 into new sets.
So the second answer is 2.

题目大意

query1要求移动一个区间内的数的花费总和。query要求在移动1~n的过程中,数字x被移动的次数。

解题思路

query1即求lowbit数组的前缀和,可以先写出1~10的二进制表示,找到规律,这样对于某个特定的数,只需要枚举它的每个二进制位即可。query2同样可以根据简单的例子找到规律,就是参照树状数组单点修改的过程,求出这个过程中lowbit数组的转移次数。

AC代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<cmath>
#include<vector>
#include<string>
#include<queue>
#include<list>
#include<stack>
#include<set>
#include<map>
#define ll long long
#define ull unsigned long long
#define db double
//#define rep(i,n) for(int i = 0;i < n; i++)
//#define rep(i,n) for(int i = 0;i < n; i++)
#define rep(i,a,b) for (int i=(a),_ed=(b);i<=_ed;i++)
//#define rep(i,a,b) for(int i=(a);i<(b);++i)
#define fil(a,b) memset((a),(b),sizeof(a))
#define cl(a) fil(a,0)
#define pb push_back
#define mp make_pair
#define exp 2.7182818
#define PI 3.141592653589793238462643383279502884
#define inf 0x3f3f3f3f
#define fi first
#define se second
#define eps 1e-6
#define MOD 1000000007ll
using namespace std;
ll n;
int lowbit(int x) {return x&(-x);}
ll lowbit(ll x) {return x&(-x);}
ll cal(ll x)
{
    ll res=0;
    ll test=x;
    int xx=0;
    while(test)
    {
        xx++;
        test>>=1;
    }
    for(int i=1;i<=xx;++i)
    {
        ll group=(x+1)/(1ll<<i);
        res+=group*(1ll<<(i-1));
        ll remain=((ll)x+1)-(group*(1ll<<i));
        remain=max(0ll,remain-(1ll<<(i-1)));
        if(remain>0ll) res+=(1ll<<(i-1));
    }


    return res;
}
int process(ll x)
{
    int step=0;
    while(x<=n)
    {
        step++;
        x+=lowbit(x);

    }
    return step;
}
int main(void) 
{
    //freopen("input.in","r",stdin);
    //freopen("output.out","w",stdout);

    int q;
    int op;
    ll from,to,x;


    while(scanf("%lld%d",&n,&q)!=EOF)
    {
        for(int i=1;i<=q;++i)
        {   
            scanf("%d",&op);
            if(op==1)
            {
                scanf("%lld%lld",&from,&to);
                printf("%lld\n",cal(to)-cal(from-1));
            }
            else
            {
                scanf("%lld",&x);
                printf("%d\n",process(x));
            }
        }
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/xj949967574/article/details/77984544
今日推荐