Aninteresting game hdu-5975(树状数组原理)

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 ilowbit(i)+1,i1i−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,RL,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个集合,第 i 个集合的数是[i-lowbit(i)+1,i-1]+i;有m个询问,询问方式有两种,第一种方式是集合[a,b]共有多少个数?第二种方式是数字x在几个集合里面?

input
先输入n和m,然后输入1或者2,若是1,接着输入a和b;若是2,输入x
Output
对于每个询问输出一个结果

思路:了解了有关于树状数组的知识后能够知道:

集合:1 2 3 4 5 6 7 8
长度:1 2 1 4 1 2 1 8
能够发现每k个 k ∈{1,2,4,8……}会出现1个k的倍数,所以我们能够知道[1,i]中有多少个不同的k以及每个k的个数p。所以能够求得[1,i]的长度和是多少,进而求得[a,b]的长度和。要找到x在几个集合中,可用x=x+lowbit(x)找出有多少满足条件的x,就能得到集合的个数

AC代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <queue>
 5 #include <algorithm>
 6 #include <map>
 7 #include <set>
 8 #include <stdlib.h>
 9 #include <stack>
10 #include <vector>
11 #include <cmath>
12 #define ll long long
13 using namespace std;
14 ll tmp[100];
15 ll count_ans(ll x)
16 {
17     ll ans=0,cnt;
18     for(int i=0;tmp[i]<=x;i++)
19     {
20         ans=ans+((x/tmp[i]-x/tmp[i+1])*tmp[i]);
21     }
22     return ans;
23 }
24 int main()
25 {
26     ll n,a,b;
27     int m,x;
28     tmp[0]=1;
29     for(int i=1;i<63;i++)
30     {
31         tmp[i]=tmp[i-1]*2;
32     }
33     while(~scanf("%lld%d",&n,&m))
34     {
35         while(m--)
36         {
37             scanf("%d",&x);
38             if(x==1)
39             {
40                 scanf("%lld%lld",&a,&b);
41                 printf("%lld\n",count_ans(b)-count_ans(a-1));
42             }
43             if(x==2)
44             {
45                 scanf("%lld",&a);
46                 int ans=0;
47                 while(a<=n)
48                 {
49                     ans++;
50                     a+=(a&(-a));
51                 }
52                 printf("%d\n",ans);
53             }
54         }
55     }
56     return 0;
57 }
View Code

 

posted @ 2017-06-08 16:59  Wally的博客  阅读(1098)  评论(0编辑  收藏  举报