题目链接:点击打开链接
//hdu5975
//题目大意:1-n的序列,对i操作则把[i- lowbit(i)+ 1, i]放到一个集合里,每放一个数都有一个花费;
// 两种询问:1、对[l,r]整个区间操作,需要多少花费
// 2、整个区间所有中 会把x放到一个集合里 的操作的数量
//大概思路:
// 对i操作将会花费i- (i- lowbit(i)+ 1)+ 1== lowbit(i);
// 则对[l,r]整个区间操作,既是对i属于[l,r]的lowbit(i)求和,sum(r)- sum(l- 1);
// 然后就是如何算出sum(n);
// 打表后发现,1到2^k的lowbit序列刚好是是2^k+ 1到2^(k+ 1)序列(第2^(k+ 1)项加上)
// 所以 sum(2^k)= sum(2^(k- 1))* 2+ 2^(k- 1);
#include <iostream>
#include <algorithm>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
#define ll long long
using namespace std;
ll k[65], s[65];
void init()
{
k[0]= 1; s[0]= 1;
ll i= 1;
while(i< 64)
{
k[i]= k[i- 1]* 2;
s[i]= s[i- 1]* 2+ k[i- 1];
i++;
}
}
ll sum(ll n)
{
if(n== 0) return 0;
if(n== 1) return 1;
int j= lower_bound(k, k+ 64, n)- k;
if(k[j]> n) j--;
return s[j]+ sum(n- k[j]);
}
int main()
{
ll n, q;
init();
while(scanf("%lld%lld", &n, &q)== 2)
{
int op;
while(q--)
{
scanf("%d", &op);
if(op== 1)
{
ll x, y; scanf("%lld%lld", &x, &y);
ll sx= sum(x- 1);
ll sy= sum(y);
printf("%lld\n", sum(y)- sum(x- 1));
} else
{
ll x; scanf("%lld", &x);
int ans= 0;
while(x<= n)
{
ans++; x+= x& -x;
}
printf("%lld\n", ans);
}
}
}
return 0;
}