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 Inputios

10 2
1 8 9
2 6

Sample Output數組

9
2

        
 

Hintide

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在幾個集合裏面?this

input
先輸入n和m,而後輸入1或者2,如果1,接着輸入a和b;如果2,輸入x
Output
對於每一個詢問輸出一個結果spa

思路:瞭解了有關於樹狀數組的知識後可以知道:code

集合: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,就能獲得集合的個數orm

AC代碼:xml

 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
相關文章
相關標籤/搜索