线段树解法
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=50005;
int tree[maxn<<2],w[maxn];
int N;
void build(int id,int l,int r){
if(l==r){
tree[id]=w[l];
return;
}
int mid=(l+r)>>1;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
tree[id]=tree[id<<1]+tree[id<<1|1];
}
void update(int id,int l,int r,int x,int d){
if(l==r){
tree[id]+=d;
return;
}
int mid=(l+r)>>1;
if(x<=mid)update(id<<1,l,mid,x,d);
else update(id<<1|1,mid+1,r,x,d);
tree[id]=tree[id<<1]+tree[id<<1|1];
}
int query(int id,int l,int r,int a,int b){
if(a<=l&&r<=b){
return tree[id];
}
int mid=(l+r)>>1;
int ans=0;
if(a<=mid){
ans=query(id<<1,l,mid,a,b);
}
if(b>mid){
ans+=query(id<<1|1,mid+1,r,a,b);
}
return ans;
}
int main(){
int T;
scanf("%d",&T);
for(int i=1;i<=T;i++){
printf("Case %d:\n",i);
scanf("%d",&N);
for(int j=1;j<=N;j++){
scanf("%d",&w[j]);
}
build(1,1,N);
char a[10];
int x,y;
while(scanf("%s",a),a[0]!='E'){
scanf("%d%d",&x,&y);
if(a[0]=='Q'){
printf("%d\n",query(1,1,N,x,y));
}
else if(a[0]=='A'){
update(1,1,N,x,y);
}
else{
update(1,1,N,x,-y);
}
}
}
}
树状数组写法
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=50005;
int sum[maxn];
int N;
void add(int k,int d){
while(k<=N){
sum[k]+=d;
k+=k&(-k);
}
}
int query(int k){
int ans=0;
while(k>0){
ans+=sum[k];
k-=k&(-k);
}
return ans;
}
int main(){
int T;
scanf("%d",&T);
for(int i=1;i<=T;i++){
printf("Case %d:\n",i);
scanf("%d",&N);
memset(sum,0,sizeof(sum));
int x,y;
for(int j=1;j<=N;j++){
scanf("%d",&x);
add(j,x);
}
char a[10];
while(scanf("%s",a),a[0]!='E'){
scanf("%d%d",&x,&y);
if(a[0]=='Q'){
printf("%d\n",query(y)-query(x-1));
}
else if(a[0]=='A'){
add(x,y);
}
else{
add(x,-y);
}
}
}
}