线段树模板,就不写其他的了
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct node
{int l,r,sum;
}tr[200005];
int a[50001];
int i,j,k,m,n,t,x,y;
int sum1;
void build(int L,int R,int num)
{tr[num].l=L;
tr[num].r=R;
if(L==R)tr[num].sum=a[L]; //已到单点,赋值;
else
{build(L,(L+R)/2,2*num); //此处是向下向内部递归,注意头尾标号;
build((L+R)/2+1,R,2*num+1);
tr[num].sum=tr[num*2+1].sum+tr[num*2].sum; //注意,大区间(非单点)的值一定要在递归回来之后赋值,否则小区间或单点的值为零;
}
}
void add(int x,int y,int num)
{ tr[num].sum+=y; //所有包含点x的大区间都要变化,此处从上往下传递变化;
if(tr[num].l==tr[num].r)return ;
if(x>(tr[num].l+tr[num].r)/2)add(x,y,num*2+1);
if(x<=(tr[num].l+tr[num].r)/2)add(x,y,num*2);
}
void query(int L,int R,int num)
{if(tr[num].l>=L && tr[num].r<=R)
{sum1+=tr[num].sum;
return ;
}
int mid=(tr[num].l+tr[num].r)/2;
if(mid<L)query(L,R,num*2+1); //要找的线段在当前线段右半部;
else if(mid>=R)query(L,R,num*2); //要找的线段在当前线段左半部;
else //要找的线段一部分在左,一部分在右,两边都找;
{query(L,R,num*2+1);
query(L,R,num*2);
}
}
int main()
{scanf("%d",&t);
k=t;
while(t--)
{scanf("%d",&n);
printf("Case %d:\n",k-t);
for(i=1;i<=n;i++)scanf("%d",&a[i]);
build(1,n,1);
char str[5];
while(~scanf("%s",&str))
{if(str[0]=='E')break;
scanf("%d%d",&x,&y);
sum1=0;
if(str[0]=='A')add(x,y,1);
if(str[0]=='S')add(x,-y,1);
if(str[0]=='Q')
{query(x,y,1);
printf("%d\n",sum1);
}
}
}
return 0;
}