初学线段树的题。。主要考察对线段树的操作吧。。。每次更新当个兵营的时候对其父区间也进行更新,查询时找到该区间输出
小萌学姐说开数组的时候开四倍大为宜。。。
嗯。。。下面是代码:
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> using namespace std; const int maxn=50000; struct unit{ int l; int r; int sum; }save[(maxn+5)*9]; int a[maxn+5]; void build(int l,int r,int index){ save[index].l=l; save[index].r=r; if(l==r){ save[index].sum=a[l]; return; } int middle = (l+r)/2; build(l, middle, 2*index); build(middle+1, r, 2*index+1); save[index].sum=save[2*index].sum+save[2*index+1].sum; } void update(int number,int index,int ans){ //cout<<index<<" l "<<save[index].l<<" r "<<save[index].r<<" num "<<number<<endl; save[index].sum += ans; if(save[index].l==save[index].r&&save[index].l==number){ return; } int middle = (save[index].l+save[index].r)/2; if(middle>=number){ update(number, 2*index, ans); }else{ update(number, 2*index+1, ans); } } int getSum(int l,int r,int index){ if(save[index].l==l&&save[index].r==r){ return save[index].sum; } int middle = (save[index].l+save[index].r)/2; if(middle<l){ return getSum(l, r, 2*index+1); }else if(middle>=r){ return getSum(l,r,2*index); }else{ return getSum(l, middle, 2*index)+getSum(middle+1, r, 2*index+1); } } int main(){ int t,rnd=1; scanf("%d",&t); while(t--){ printf("Case %d:\n",rnd); int n,i; memset(save, 0, sizeof(save)); scanf("%d",&n); for(i=1;i<=n;i++){ scanf("%d",&a[i]); } build(1, n, 1); string str; while(cin>>str){ //cout<<save[1].sum<<endl; if(str=="End"){ break; } int l,r; if(str[0]=='Q'){ scanf("%d%d",&l,&r); printf("%d\n",getSum(l, r, 1)); }else if(str[0]=='A'){ scanf("%d%d",&l,&r); update(l, 1, r); }else{ scanf("%d%d",&l,&r); update(l, 1, -r); } } rnd++; } return 0; }