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−1i−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.
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−1i−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 ",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 ",ans); 53 } 54 } 55 } 56 return 0; 57 }