您的位置:首页 > 其它

2013暑假江西联合训练赛(赛后) 二进制求和 (树状数组,这里需要变形下)

2013-09-02 19:43 316 查看

Problem Description

平时我们经常会将一个数用二进制的形式来表示,我们用 BSUM(X) 表示X用二进制形式表示中1的个数。现在给你一个长度为n (n<=100000)的数组g (0<=g[i]<10^9)。 有q(q<=100000)次操作

1 a b (1<=a<=b<=n) 表示要输出 BSUM[a]+BSUM[a+1]... BSUM[b] 的和。

2 a b (1<=a<=n,0<=b<=10^9) 表示将g[a]的值变成b,即g[a]=b

3 a b (1<=a<=b<=n) 表示g[i]=2*g[i] (a<=i<=b),即将数组从a到b的值全部都乘以2.

Input

第一行输入T(<=100),代表测试组数

每组测试先输入一行n,下一行输入n个数a[i](1<=i<=n).

然后输入q表示询问次数

接下来q行代表每次询问。

Sample Input

2
5
1 2 3 4 5
3
1 2 4
2 3 0
1 1 5
5
1 4 8 9 10
5
1 1 5
2 1 0
3 1 5
1 2 2
1 1 5


Sample Output

4
5
7
1
6

题目大意:很明显的树状数组、但需要小小的变形。

思路见代码咯

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAX 100010
using namespace std;
int c[MAX];
int b[MAX];
int BitCount(int n)         //计算二进制1的个数
{
int c=0;
for(c=0;n;++c)
{
n&=(n-1);
}
return c;
}
int lowbit(int x)
{
return x&(-x);
}
void updata(int x,int d)
{
while(x<=MAX)
{
c[x]=c[x]+d;
x=x+lowbit(x);
}
}
int sum(int x)
{
int res=0;
while(x>0)
{
res=res+c[x];
x=x-lowbit(x);
}
return res;
}
int main()
{
int t;
int n,i;
int x,y;
int p,q;
int ans;
int s,s1,s2;
scanf("%d",&t);
while(t--)
{
ans=0;
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&b[i]);
s=BitCount(b[i]);
updata(i,s);
}
scanf("%d",&p);
while(p--)
{
scanf("%d",&q);
if(q==1)
{
scanf("%d%d",&x,&y);
ans=sum(y)-sum(x-1);
printf("%d\n",ans);
}
else if(q==2)
{
scanf("%d%d",&x,&y);
s1=BitCount(y);         //统计y中1的个数
s2=BitCount(b[x]);      //统计b[x]中 1 的个数
updata(x,-s2);          //消去原有b[x] 中 1的个数
updata(x,s1);           //修改b[x] 中 1 的个数
b[x]=y;                 //一定要记住修改b[x]的值,WA了4次
}
else if(q==3)
{
scanf("%d%d",&x,&y);    //乘以2 1的个数不变
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: