入门级的树状数组直接应用,题目内容可以用数组来来模拟,意思是对下标为1~N的数组动态进行修改和统计某一特定区间[a,b]的数据总和。
树状数组之所以会比普通示和表述的动态求和快,是因为其保留了存和(开辟数组保留多项的和)的特性,但是其并不像普通示和数组那样将数组的每一项的意义都看做一样的,树状数组中下标为[2^0],[2^1],[2^2]......的意义和普通数组一致,但其他的数组项则只是表示局部(左邻区域)的和值,例如下标为[3]单单表示第三个数据的值,下标为[6]的表示第五和第六个数据和,我们要明确,树状数组是利于处理动态求和的数据存储结构,意思是说他存储的数据是完整的。
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
int T,N,e[50011],r[50011];
int sum(int num)
{
int sum=0;
while(num)
{
sum+=r[num];
num-=num&-num;
}
return sum;
}
int query(int sta,int end)
{
return sum(end)-sum(sta-1);
}
void update(int p,int m)
{
while(p<=N)
{
r[p]+=m;
p+=p&-p;
}
}
int main()
{
scanf("%d",&T);
int shit=1; //shit 用来标示是否输出 Case :?
for(int i=1;i<=T;++i)
{
memset(r,0,sizeof(r));
scanf("%d",&N);
for(int j=1;j<=N;++j) //将树状数组视作一个数据结构
{ //其包含了一切线性数组的所有信息
int c,y=j;
scanf("%d",&c);
update(j,c); //将存储看做示一种更新
}
char dos[10]; //用于命令收集
int a,b;
while(1) //以下为动态操作
{
scanf("%s",dos);
if(dos[0]=='E')
{
shit=1;
break;
}
scanf("%d%d",&a,&b);
if(dos[0]=='Q')
{
if(shit)
{
printf("Case %d:\n",i);
shit=0;
}
printf("%d\n",query(a,b));
}
else if(dos[0]=='A')
update(a,b);
else if(dos[0]=='S')
update(a,-b);
}
}
return 0;
}