zoukankan      html  css  js  c++  java
  • Aninteresting game HDU

    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. 
    InputThere 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 
    OutputFor each query, please output one line containing your answer for this querySample 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. 
    
            
     
    题意:
    多组输入,。每一组数据,有一个数字n,和一个数q,
    有1~n个数,将i放入集合中同时放入i-lowbit(i)+1~ i 的所有数。
    每向集合中放入一个数,就会消耗一点体力值。

    然后有q个询问,询问1是,给你一个l和r,问l~r每一个数都加入到集合中,会消耗多少体力值。
    2.
    1~n中,对每一个数进行加入到集合中的话,数x会被加入多少次。

    思路:
    把i放入集合就会放入i-lowbit(i)+1~i的所有数
    那么一共就是加入i - (i-lowbit(i)+1) +1 个数,即lowbit(i)个数,
    那么一个数i消耗的体力值就是lowbit(i)
    那么第一问就是让求l~r的lowbit的sum和。

    由于数据量很大,我们不能扫一遍算出,
    那么我们来分析一下是否可以优化。,
    我们知道,lowbit(i)表示的是数字i的二进制最低位代表的十进制数。
    例如6的二进制是110,最低位时第2个1,从右向左第2位,代表的十进制时2,(二进制10是十进制的2),那么lowbit(6)就是2。
    那么l~r的lowbit的sum和就是,最低位的1在0位置上的数的数量*1(代表的十进制)+ 最低位的1在1位置上的数的数量*2 +.....
    那么问题转化为如何快速的求出l~r中最低位的1在第i位的数的数量,
    我们知道这样的一个求解方法(容斥的思想)n/(1<<P)-n/(1<<(p+1))就是·1~n中最低位的1在第p位(从右向左数,0开始计位)的数的数量。
    那么我们只需要logn来枚举每一位,然后上面的公式即可计算出每一位的数量。

    然后我们来看第二个问题,
    要找到x在几个集合中,可用x=x+lowbit(x)找出有多少满足条件的x,就能得到集合的个数

    细节见代码:
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #include <vector>
    #include <iomanip>
    #define ALL(x) (x).begin(), (x).end()
    #define rt return
    #define dll(x) scanf("%I64d",&x)
    #define xll(x) printf("%I64d
    ",x)
    #define sz(a) int(a.size())
    #define all(a) a.begin(), a.end()
    #define rep(i,x,n) for(int i=x;i<n;i++)
    #define repd(i,x,n) for(int i=x;i<=n;i++)
    #define pii pair<int,int>
    #define pll pair<long long ,long long>
    #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
    #define MS0(X) memset((X), 0, sizeof((X)))
    #define MSC0(X) memset((X), '', sizeof((X)))
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define eps 1e-6
    #define gg(x) getInt(&x)
    #define db(x) cout<<"== [ "<<x<<" ] =="<<endl;
    using namespace std;
    typedef long long ll;
    ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
    ll powmod(ll a,ll b,ll MOD){ll ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
    inline void getInt(int* p);
    const int maxn=1000010;
    const int inf=0x3f3f3f3f;
    /*** TEMPLATE CODE * * STARTS HERE ***/
    ll solve(ll x)
    {
        ll res=0ll;
        for(ll p=1ll;p<=x;p<<=1)
        {
            res+=(x/p-x/(p<<1))*p;
        }
        return res;
    }
    ll lowbit(ll x)
    {
        return x&(-x);
    }
    ll solve2(ll x,ll n)
    {
        ll res=0ll;
        while(x<=n)
        {
            res++;
            x+=lowbit(x);
        }
        return res;
    }
    
    int main()
    {
        //freopen("D:\common_text\code_stream\in.txt","r",stdin);
        //freopen("D:\common_text\code_stream\out.txt","w",stdout);
        
        ll n,q;
        while(~scanf("%lld %lld",&n,&q))
        {
            int op;
            while(q--)
            {
                scanf("%d",&op);
    
                if(op==1)
                {
                    ll l,r;
                    scanf("%lld %lld",&l,&r);
                    ll res=solve(r)-solve(l-1ll);
                    printf("%lld
    ",res );
                }else   
                {
                    ll x;
                    scanf("%lld",&x);
                    printf("%lld
    ",solve2(x,n) );
                }
            }
        }
        
        
        return 0;
    }
    
    inline void getInt(int* p) {
        char ch;
        do {
            ch = getchar();
        } while (ch == ' ' || ch == '
    ');
        if (ch == '-') {
            *p = -(getchar() - '0');
            while ((ch = getchar()) >= '0' && ch <= '9') {
                *p = *p * 10 - ch + '0';
            }
        }
        else {
            *p = ch - '0';
            while ((ch = getchar()) >= '0' && ch <= '9') {
                *p = *p * 10 + ch - '0';
            }
        }
    }

    本博客为本人原创,如需转载,请必须声明博客的源地址。 本人博客地址为:www.cnblogs.com/qieqiemin/ 希望所写的文章对您有帮助。
  • 相关阅读:
    Struts2 采用Convention-plugin 实现零配置
    xml中批量新增数据或者批量修改数据
    Linux基础笔记_05
    Linux基础笔记_03
    Linux基础笔记_02
    Linux基础笔记_01
    玩转spring boot——websocket
    获取一天中的起始时间与结束时间
    《浅谈架构之路:前后端分离模式》
    区域语言与区域语言包对照关系表
  • 原文地址:https://www.cnblogs.com/qieqiemin/p/10780837.html
Copyright © 2011-2022 走看看