題意:有N個兵營,每一個兵營都給出了人數ai(下標從1開始),有四種命令,(1)」Addij",表示第i個營地增長j人。(2)「Sub i j」,表示第i個營地減小j人。(3)「Query ij",查詢第i個營地到第j個營地的總人數。(4)」End「,表示命令結束。ios
有三種操做:詢問區間總和,增長某個兵營的兵的數目,減小某個兵營的兵的數目。實際上也只有兩個。spa
在更新的時候,每到一個區間就把當前區間的sum增長對應的數目,到達葉子結點是返回。這樣就能夠不會回溯去更新父親結點的值。查詢的時候,若是區間徹底匹配,直接返回區間的sum值,不然向下尋找,直到徹底匹配,而後返回它們的和就能夠。這時候,結果裏保存的邊界是它們真正的邊界。code
// Time 203ms; Memory 1944K
#include<iostream> #include<cstdio> #include<cstring> #define maxn 1<<17 using namespace std; int size,n,sum,all[40010]; struct line { int l,r; int n; }a[maxn]; void init() { int i; for(n=1;n<size;n<<=1); for(i=n;i<2*n;i++) { a[i].l=a[i].r=i-n+1; a[i].n=0; } for(i=n-1;i>0;i--) { a[i].l=a[2*i].l; a[i].r=a[2*i+1].r; a[i].n=0; } } void insert(int i,int x,int m) { if(x>=a[i].l && x<=a[i].r) a[i].n+=m; if(a[i].l==a[i].r) return; int mid=(a[i].l+a[i].r)/2; if(x>mid) insert(2*i+1,x,m); else insert(2*i,x,m); } void find(int x,int y,int i) { if(x==a[i].l && y==a[i].r) { sum+=a[i].n; return; } if(a[i].l==a[i].r) return; int mid=(a[i].l+a[i].r)/2; if(x>mid) find(x,y,2*i+1); else if(y<=mid) find(x,y,2*i); else { find(x,mid,2*i); find(mid+1,y,2*i+1); } } int main() { int i,j,k,t,x,y,m; char s[7]; scanf("%d",&t); for(i=0;i<t;i++) { scanf("%d",&size); init(); for(j=0;j<size;j++) { scanf("%d",&k); insert(1,j+1,k); } k=0; while(scanf("%s",s)!=EOF && strcmp(s,"End")) { if(strcmp(s,"Add")==0) { scanf("%d%d",&x,&m); insert(1,x,m); } else if(strcmp(s,"Sub")==0) { scanf("%d%d",&x,&m); insert(1,x,-m); } else { scanf("%d%d",&x,&y); sum=0; find(x,y,1); all[k++]=sum; } } printf("Case %d:\n",i+1); for(j=0;j<k;j++) printf("%d\n",all[j]); } return 0; }