题目来源: http://acm.hdu.edu.cn/showproblem.php?pid=1166
还是敌兵布阵那一题,不过这次是用的树状数组解决的。
树状数组是一个特殊的数据结构,如图。(图片来自:百度百科)
它的作用是:1,完成单点更新。2,能快速求1-x的区间的和。
注意,数组里面没有存放每一个点的值,存放的只是上层节点的值(红色),当然存放上层节点的值,只是为了能快速的求出区间1-x的和。
#include<cstdio>
#include<cstring>
using namespace std ;
int n ;
const int maxn = 50005 ;
int lowbit(int x){ ///显示每一个节点管辖的范围的大小
return x&(-x) ; ///返回值就是管辖范围,自己可以计算验证一下。
}
void update(int x,int *c,int d){ ///从数组最底层更新至根节点
for(int i=x;i<=n;i+=lowbit(i)){
c[i]+=d ;
}
}
int summary(int x,int *c){ ///求和,求的和是从1到x的和
int sum=0 ;
for(int i=x;i>0;i-=lowbit(i)){
sum+=c[i] ;
}
return sum ;
}
int main(){
int T ;
scanf("%d",&T);
int cas=1;
while(T--){
scanf("%d",&n);
int arry[maxn] ; ///这个数组没有存放每一个点的值,而是节点的值。
memset(arry,0,sizeof(arry));
for(int i=0;i<n;i++){
int a ;
scanf("%d",&a);
update(i+1,arry,a);
}
printf("Case %d:\n",cas++);
while(true){
char str[10] ;
scanf("%s",str);
if(str[0]=='E')break ;
else if(str[0]=='A'){
int a,b ;
scanf("%d%d",&a,&b);
update(a,arry,b);
}else if(str[0]=='S'){
int a,b ;
scanf("%d%d",&a,&b);
update(a,arry,-b);
}else{
int a,b ;
scanf("%d%d",&a,&b);
printf("%d\n",summary(b,arry)-summary(a-1,arry));
}
}
}
return 0;
}