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.
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行代表每次询问。
每组测试先输入一行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; }