题意:
有n个集合,第i个集合里面包含在范围[i-lowbit(i)+1, i]内的所有数
有2种询问,1 x y表示集合a到集合b的长度和;2 x表示有多少个集合里面包含数字x
对于第二个询问非常简单
只要对x不停地+lowbit(x)就好了,看加多少次会超过n
对于第一个询问,先看集合与长度的对应关系:
集合:1 2 3 4 5 6 7 8
长度:1 2 1 4 1 2 1 8
很快就可以发现这是个树状数组,并且它对应的原序列正好每个位置上的值都为1
也就是:每隔一个数+1(对答案的贡献就是(y-(x-1))*1),然后每隔两个数+1(对答案的贡献就是(y/2-(x-1)/2)*1)
再每隔4个数+1(对答案的贡献就是(y/4-(x-1)/4)*2)……
预处理2^n,之后上面的贡献全加在一起就好了
#include<stdio.h>
#define LL long long
LL er[63] = {1};
int main(void)
{
LL n, q, ans, a, b, t, i;
for(i=1;i<=62;i++)
er[i] = er[i-1]*2;
while(scanf("%lld%lld", &n, &q)!=EOF)
{
while(q--)
{
ans = 0;
scanf("%lld", &t);
if(t==2)
{
scanf("%lld", &a);
while(a<=n)
{
a += a&-a;
ans++;
}
}
else
{
scanf("%lld%lld", &a, &b);
for(i=0;i<=62;i++)
{
if(i<=1)
ans += (b/er[i]-(a-1)/er[i]);
else
ans += (b/er[i]-(a-1)/er[i])*er[i-1];
}
}
printf("%lld\n", ans);
}
}
return 0;
}