题意:中文题,省。
解法:线段树。
注意:输入,输出最后用scanf(),printf(),其他的可能超时。
ac代码:
View Code
//线段树,节点更新,区间求和 #include<iostream> #include<string> using namespace std; const int M=50000+10;//最大区间 int num[M];//记录每一个营的人数 struct treestruct { int left;//左区间 int right;//右区间 int sum;//区间求和 }node[M*3];//节点数大约是最大区间的3倍 int build(int low,int top,int index)//建树:父节点是左右节点之和 { node[index].left=low; node[index].right=top; if(low==top) //是否递归到最低 { return node[index].sum=num[low]; } int mid=(low+top)>>1; return node[index].sum=build(low,mid,index*2)+build(mid+1,top,index*2+1);//父节点是左右节点之和 } void updata(int k,int s,int index)//在节点k上加上s,所以k的每一个父节点都要加s { node[index].sum+=s; if(node[index].left==node[index].right&&node[index].left==k) { return ; } int mid=(node[index].left+node[index].right)>>1; if(mid>=k) //k在左子树中 updata(k,s,index*2); else //k在右子树中 updata(k,s,index*2+1); } int search(int l,int r,int index) { if(node[index].left==l&&node[index].right==r)//找到完全重合的区间,直接返回node[].sum值 return node[index].sum; int mid=(node[index].left+node[index].right)>>1; if(mid>=r) //搜索区间位于左子树 return search(l,r,index*2); else if(mid<l) //搜索区间位于右子树 return search(l,r,index*2+1); else //搜索区间位于左右子树,即将区间分为2部分 { return search(l,mid,index*2)+search(mid+1,r,index*2+1); } } int main() { int t; scanf("%d",&t); int k=1; while(t--) { int i,j; int n; scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%d",&num[i]); } build(1,n,1); printf("Case %d:\n",k++); char ch[10]; int a,b; while(scanf("%s",ch)) { if(ch[0]=='A') { scanf("%d%d",&a,&b); updata(a,b,1); } if(ch[0]=='S') { scanf("%d%d",&a,&b); updata(a,-b,1); } if(ch[0]=='Q') { scanf("%d%d",&a,&b); printf("%d\n",search(a,b,1)); } if(ch[0]=='E') break; } } return 0; } /* 10 1 2 3 4 5 6 7 8 9 10 Query 1 3 Add 3 6 Query 2 7 Sub 10 2 Add 6 3 Query 3 10 End */