嘿嘿,第一次写线段树!思路还是乱的!
为便于理解,我拿第一组数据画了二叉树![a,b]:sum a,b表示该结点的范围,红色字体(sum)表示该范围内的和,等于左右孩子结点和相加

# include<stdio.h>
# include<string.h>
const int MAX=50005;
struct node
{
int l;
int r;
int sum;
}tree[MAX*4];
int sol[MAX];
void Bulid(int rt,int l,int r)
{
int mid;
tree[rt].l=l;
tree[rt].r=r;
if(r==l)
{
tree[rt].sum=sol[l];
return;
}
mid=(l+r)/2;
Bulid(rt*2,l,mid);
Bulid(rt*2+1,mid+1,r);
tree[rt].sum=tree[rt*2].sum+tree[rt*2+1].sum;
}
void Add(int rt,int a,int b)
{
int mid;
if(tree[rt].l==tree[rt].r)
{
tree[rt].sum+=b;
return;
}
mid=(tree[rt].l+tree[rt].r)/2;
if(a<=mid)
Add(2*rt,a,b);
else
Add(2*rt+1,a,b);
tree[rt].sum=tree[2*rt].sum+tree[2*rt+1].sum;
}
int Query(int rt,int a,int b)
{
int ans=0,mid;
if(tree[rt].l>=a&&tree[rt].r<=b)
return tree[rt].sum;
mid=(tree[rt].l+tree[rt].r)/2;
if(mid>=a)
ans+=Query(2*rt,a,b);
if(b>mid)
ans+=Query(2*rt+1,a,b);
return ans;
}
int main()
{
int t,i,n,k,a,b,flag;
char s[10];
scanf("%d",&t);
for(k=1;k<=t;k++)
{
flag=0;
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&sol[i]);
Bulid(1,1,n);
while(~scanf("%s",s)&&strcmp(s,"End")!=0)
{
scanf("%d%d",&a,&b);
if(strcmp(s,"Add")==0)
Add(1,a,b);
else if(strcmp(s,"Sub")==0)
Add(1,a,-b);
else if(strcmp(s,"Query")==0)
{
if(!flag)
{
printf("Case %d:\n",k);
flag++;
}
printf("%d\n",Query(1,a,b));
}
}
}
return 0;
}