线段树模板,就不写其他的了
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; struct node {int l,r,sum; }tr[200005]; int a[50001]; int i,j,k,m,n,t,x,y; int sum1; void build(int L,int R,int num) {tr[num].l=L; tr[num].r=R; if(L==R)tr[num].sum=a[L]; //已到单点,赋值; else {build(L,(L+R)/2,2*num); //此处是向下向内部递归,注意头尾标号; build((L+R)/2+1,R,2*num+1); tr[num].sum=tr[num*2+1].sum+tr[num*2].sum; //注意,大区间(非单点)的值一定要在递归回来之后赋值,否则小区间或单点的值为零; } } void add(int x,int y,int num) { tr[num].sum+=y; //所有包含点x的大区间都要变化,此处从上往下传递变化; if(tr[num].l==tr[num].r)return ; if(x>(tr[num].l+tr[num].r)/2)add(x,y,num*2+1); if(x<=(tr[num].l+tr[num].r)/2)add(x,y,num*2); } void query(int L,int R,int num) {if(tr[num].l>=L && tr[num].r<=R) {sum1+=tr[num].sum; return ; } int mid=(tr[num].l+tr[num].r)/2; if(mid<L)query(L,R,num*2+1); //要找的线段在当前线段右半部; else if(mid>=R)query(L,R,num*2); //要找的线段在当前线段左半部; else //要找的线段一部分在左,一部分在右,两边都找; {query(L,R,num*2+1); query(L,R,num*2); } } int main() {scanf("%d",&t); k=t; while(t--) {scanf("%d",&n); printf("Case %d:\n",k-t); for(i=1;i<=n;i++)scanf("%d",&a[i]); build(1,n,1); char str[5]; while(~scanf("%s",&str)) {if(str[0]=='E')break; scanf("%d%d",&x,&y); sum1=0; if(str[0]=='A')add(x,y,1); if(str[0]=='S')add(x,-y,1); if(str[0]=='Q') {query(x,y,1); printf("%d\n",sum1); } } } return 0; }