HDU-1166-敌兵布阵(树状数组)
http://acm.hdu.edu.cn/showproblem.php?pid=1166
初学树状数组,,
题目大意:更新点查区间,,
简单介绍一下树状数组,看下图。
c1 = a1
c3 = a3
c4 = a1 + a2 + a3 + a4
c5 = a5
c6 = a5 + a6
c7 = a7
c8 = a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8
c9=a9c10=a9+a10
对于序列a,我们设一个数组C定义C[i] = a[i – 2^k + 1] + … + a[i],k为i在二进制下末尾0的个数
求2^k
求x在二进制下末尾0的个数(第一个一出现的位置)
int lowbit(int x)
{
return x&(x^(x-1));
}
将a[p]的值加上一个值x
void update(int p,int x)
{
while(p<=n)
{
c[p]+=x;
p+=lowbit(p);
}
}
求前p项和
int sum(int p)
{
int sum=0;
while(p>0)
{
sum+=c[p];
p-=lowbit(p);
}
return sum;
}
题目代码:
#include<cstdio>
#include<cstring>
#define lowbit(x) (x&(x^(x-1)))
#define maxn 50010
using namespace std;
int c[maxn];
int n;
void update(int p,int x)///给 a[p] 加上 x
{
while(p<=n){
c[p]+=x;
p+=lowbit(p);
}
}
int sum(int p) ///求前P项的和
{
int sum=0;
while(p>0){
sum+=c[p];
p-=lowbit(p);
}
return sum;
}
int main()
{
int T,t=0;
char str[10];
scanf("%d",&T);
while(T--)
{
int x,y;
scanf("%d",&n);
memset(c,0,sizeof(c));
for(int i=1;i<=n;i++){
scanf("%d",&x);
update(i,x);
}
printf("Case %d:\n",++t);
while(scanf("%s",str)&&str[0]!='E'){
scanf("%d %d",&x,&y);
if(str[0]=='A')
update(x,y);
else if(str[0]=='S')
update(x,-y);
else if(str[0]=='Q'){
printf("%d\n",sum(y)-sum(x-1));
}
}
}
return 0;
}
参考文章:http://blog.csdn.net/cambridgeacm/article/details/7771782