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 }