#include<iostream> using namespace std; const int MAX=50000; int tree[(MAX+1)*4];//n个叶子就有2*n-4*n个节点 int a[MAX+1]; int n; void getup(int root){ return void(tree[root]=tree[root*2]+tree[root*2+1]);//两个孩子分别是root*2 和root*2+1 } void btree(int l,int r,int root){//建树 if(l==r){ tree[root]=a[l]; return ; } int mid=(l+r)>>1; btree(l,mid,root*2); btree(mid+1,r,root*2+1);//因为向下取整 mid必须加一 不然结束不了 getup(root); } int myquery(int l,int r,int L,int R,int root){//整个的思想是区间和肯定可以用二分的区间表示 if(l<=L&&r>=R) return tree[root]; int mid=(L+R)>>1; long long sum=0; if(l<=mid) sum+=myquery(l,r,L,mid,root*2);//两边相加 if(r>mid) sum+=myquery(l,r,mid+1,R,root*2+1); return sum; } void add(int i,int value,int l,int r,int root){//重点!! 更新的过程 if(l==r) {tree[root]+=value;return ;} int mid=(l+r)>>1; if(i<=mid) add(i,value,l,mid,root*2); else add(i,value,mid+1,r,root*2+1); getup(root); } int main(){ int t; cin>>t; int i=1; while(i<=t){ int flag=1; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); btree(1,n,1); char ss[10]; while(~scanf("%s",ss)){ if(ss[0]=='A'){ int i,value; scanf("%d %d",&i,&value); add(i,value,1,n,1); } if(ss[0]=='S'){ int i,value; scanf("%d %d",&i,&value); add(i,-1*value,1,n,1); } if(ss[0]=='Q'){ int a ,b; scanf("%d%d",&a,&b); if(flag){printf("Case %d:\n",i);flag=0;} printf("%d\n",myquery(a,b,1,n,1)); } if(ss[0]=='E') break; } i++; } }
题目链接:acm.hdu.edu.cn/status.php?user=YZBPXX&pid=1166&status=5