AC代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<algorithm>
using namespace std;
const int MAX=5e4+10;
int a[MAX];
struct Tree
{
int l,r,value;
}tree[4*MAX];
void build(int x,int l,int r)//x当前节点编号,l和r为当前节点代表的区间范围
{
tree[x].l=l;
tree[x].r=r;
if(l==r)//l=r到了叶子节点(无子节点了),直接更新信息并退出递归
{
tree[x].value=a[l];
return;
}
int mid=(l+r)/2;//把当前区间拆成更小的两段
build(2*x,l,mid);
build(2*x+1,mid+1,r);
tree[x].value=(tree[2*x].value+tree[2*x+1].value);//当前区间最大值为两个子区间的最大值
}
void Add(int x,int pos,int w)//x当前节点,pos要修改的位置(叶节点),w要变成的值
{
if(tree[x].l==tree[x].r&&tree[x].l==pos)//到达要修改的位置pos(叶节点),将其值进行修改
{
tree[x].value=w+tree[x].value;
return ;
}
int mid=(tree[x].l+tree[x].r)/2;
if(pos<=mid) Add(2*x,pos,w);
else Add(2*x+1,pos,w);
tree[x].value=(tree[2*x].value+tree[2*x+1].value);//递归处理完子节点,更新当前节点维护最大值信息
}
int query(int x,int l,int r)//x当前节点编号,l和r为询问的区间范围
{
if(tree[x].l==l&&tree[x].r==r)//询问区间为x代表的区间
return tree[x].value;
int mid=(tree[x].l+tree[x].r)/2;
if(r<=mid){return query(2*x,l,r);}//询问的区间都在左子树
else if(mid+1<=l){return query(2*x+1,l,r);}//询问的区间都在右子树
else
return (query(2*x,l,mid)+query(2*x+1,mid+1,r));//询问的区间跨过当前中点将其拆分两段取最大值
}
int main()
{
int T;
scanf("%d", &T);
for (int i = 1; i <= T; i++)
{
printf("Case %d:\n", i);
int n,x,y;
scanf("%d", &n);
for(int i=1;i<=n;i++)
{
scanf("%d", &a[i]);
}
build(1, 1, n);
while(1)
{
char ch[10];
scanf("%s", ch);
if (ch[0] == 'E')
break;
else
{
scanf("%d %d", &x, &y);
if (ch[0] == 'Q')
printf("%d\n", query(1, x, y));
else
{
if (ch[0] == 'S')
y = -y;
Add(1, x, y);
}
}
}
}
}