基础线段树,插点问线
//线段树,基础的插点问线
#include<stdio.h>
#include<stdlib.h>
#define L(t)(t<<1)
#define R(t)(t<<1|1)
#define MID(a,b)((a+b)>>1)
const int MAX=50002;
struct Tree
{
int l,r,sum;
}T[MAX<<2];
int n,ans,a[MAX];
void Build(int root,int l,int r)
{
T[root].l=l;T[root].r=r;
if(l==r)
{T[root].sum=a[l]; return;}//找到最小的儿子后开始向上递归,传值给父亲
int m=MID(T[root].l,T[root].r);
Build(L(root),l,m);
Build(R(root),m+1,r);
T[root].sum=T[L(root)].sum+T[R(root)].sum;//父亲的值为两个儿子的值
}
void modify(int root,int pos,int val)
{
if(T[root].r==T[root].l)
T[root].sum+=val;
else
{
int m=MID(T[root].l,T[root].r);
if(m>=pos)
modify(L(root),pos,val);
else
modify(R(root),pos,val);
T[root].sum=T[L(root)].sum+T[R(root)].sum;//同理,更新时也要更新父亲的值
}
}
void query(int root,int l,int r)
{
if(T[root].l>=l&&T[root].r<=r)
{ans+=T[root].sum; return;}
int m=MID(T[root].l,T[root].r);
if(m>=r)
query(L(root),l,r);//此处需注意
else if(l>m)
query(R(root),l,r);//同上,这就是插点问线,与插线问点的不同之处
else //要查询的值横跨两个区间
{
query(L(root),l,m);
query(R(root),m+1,r);
}
}
int main()
{
char ask[10];
int T,i,j,x,y;
scanf("%d",&T);
for(i=1;i<=T;i++)
{
scanf("%d",&n);
for(j=1;j<=n;j++)
scanf("%d",&a[j]);
Build(1,1,n);
printf("Case %d:\n",i);
while(scanf("%s",ask)&&ask[0]!='E')
{
scanf("%d%d",&x,&y);
if(ask[0]=='Q')
{
ans=0;
query(1,x,y);
printf("%d\n",ans);
}
else if(ask[0]=='S')
modify(1,x,-y);
else if(ask[0]=='A')
modify(1,x,y);
}
}
return 0;
}