每组数据最多有40000条命令
解析:本题要求实现增减、查询特定结点的数值,因此可用线段树中的单点更新算法即可。更新过后的叶子节点自动将父亲结点更新。
#include
#include
#include
#define MAX 500000
using namespace std;
int sum[MAX*2+10];
int plusnode(int root)
{
return sum[root]=sum[root<<1]+sum[root<<1|1];
}
void buildtree(int l,int r,int root)
{
if(l==r)
{
scanf("%d",&sum[root]);//初始化结点
return;
}
int mid=(l+r)>>1;
buildtree(l,mid,root<<1);
buildtree(mid+1,r,root<<1|1);
plusnode(root);//每次建树后自动将父节点更新为儿子结点之和
}
void update(int l,int r,int root,int p,int add)
{
if(l==r)//为叶子节点
{
sum[root]+=add;
return;
}
int mid=(l+r)>>1;
if(p<=mid){
update(l,mid,root<<1,p,add);
}
else{
update(mid+1,r,root<<1|1,p,add);
}
plusnode(root);
}
int query(int l,int r,int root,int L,int R)
{
if(L<=l&&R>=r)//所求区间在当前区间范围内
{
return sum[root];
}
int mid=(l+r)>>1;
int ans=0;//定义ans初始化为0,仅当查询的是叶子结点时,ans值才不会被初始化
if(L<=mid)
{
ans+=query(l,mid,root<<1,L,R);
}
if(R>mid)
{
ans+=query(mid+1,r,root<<1|1,L,R);
}
return ans;
}
int main(){
int T,N;
int a,b;
char que[10];
scanf("%d",&T);
for(int I=1;I<=T;I++){
printf("Case %d:\n",I);
scanf("%d",&N);
buildtree(1,N,1);
while(scanf("%s",que)&&que[0]!='E'){
scanf("%d%d",&a,&b);
if(que[0]=='A')
{
update(1,N,1,a,b);
}
else if(que[0]=='S')
{
update(1,N,1,a,-b);
}
else{
int ans=query(1,N,1,a,b);
printf("%d\n",ans);
}
}
}
return 0;
}