敌兵布阵
测试样例:
1 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
输出:
Case 1:
6
33
59
#include<iostream> #include<map> #include<cstdio> #include<algorithm> #include<vector> using namespace std; const int N=1e5+5; int f[3*N],a[N]; void build(int root,int left,int right){ if(left==right){ f[root]=a[left]; return; } int mid,rt; rt=root<<1; mid=(left+right)>>1;//把这几行当成最后要执行的 build(rt,left,mid);//最后一个左边递归包含的两个展开的,满足条件的,能完整运行完递归的内容。 build(rt+1,mid+1,right);//递归到最深层一定是左子叶是left=right=1,右子叶是left=right=2; f[root]=f[rt]+f[rt+1]; } void update(int root,int left,int right,int pos,int val){ if(left==right){ f[root]+=val; return; } int mid,rt; rt=root<<1;//root相当于一个节点,rt相当于节点延伸出去的两个子节点。 mid=(left+right)>>1; if(pos<=mid){ update(rt,left,mid,pos,val);//这里也有相互包含关系。 }else{ update(rt+1,mid+1,right,pos,val);//和build一样只不过是父节点只包含了一个儿子。 } f[root]=f[rt]+f[rt+1]; } int query(int root,int left,int right,int qleft,int qright){ if(qleft<=left&&right<=qright){ return f[root]; } int mid,rt; rt=root<<1; mid=(left+right)>>1; int ans=0; if(qleft<=mid){ ans+=query(rt,left,mid,qleft,qright);//第一步确定左边或者右边的方向大方向祖先的俩儿子,有则选之。 } if(mid<qright){ ans+=query(rt+1,mid+1,right,qleft,qright); } return ans; } int main(){ int T,n; char s[5]; scanf("%d",&T); for(int t=1;t<=T;t++){ printf("Case %d:\n",t); scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } build(1,1,n); while(cin>>s){ int i,j; if(s[0]=='E'){ break; } scanf("%d%d",&i,&j); if(s[0]=='A'){ update(1,1,n,i,j); }else if(s[0]=='S'){ update(1,1,n,i,-j); }else { printf("%d\n",query(1,1,n,i,j)); } } } return 0; }