解析:线段树的单点更新,线段树套用线段树的模板。、
#include <cstdio> #include <cstring> using namespace std; const int N = 50005; int s[N << 2], L[N << 2], R[N << 2]; int a[N]; void build(int u,int l,int r) { if(l == r) { R[u] = L[u] = l; s[u] = a[l]; return ; } int mid = (l + r) / 2; build(u*2,l,mid); build(u*2+1,mid+1,r); L[u] = l; R[u] = r; s[u] = s[u*2] + s[u*2+1]; } void modify(int u,int x,int v) { if(R[u] == x && L[u] == x) { //叶子节点 s[u] = s[u] + v; return ; } //非叶子节点 int mid = (L[u] + R[u]) / 2; if(x <= mid) { modify(u*2,x,v); }else { modify(u*2+1,x,v); } s[u] = s[u] + v; } int query(int u,int l,int r) { if(l <= L[u] && R[u] <= r) { return s[u]; } int mid = (L[u] + R[u]) / 2; if(r <= mid) { //如果左区间有涉及 return query(u*2,l,r); //则递归左边子树 }else if(l > mid) { //如果右区间有涉及 return query(u*2+1,l,r); //则递归右字数 }else { //如果都没有涉及 return query(u*2,l,r) + query(u*2+1,l,r); } } int main() { int T,n,cas = 1; int l,r; int x,v; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i = 1; i <= n; i++) { scanf("%d",&a[i]); } memset(s,0,sizeof(s)); L[1] = 1; R[1] = n; build(1,L[1],R[1]); char cmd[20]; printf("Case %d:\n",cas++); while(scanf("%s",cmd) != EOF) { if(cmd[0] == 'Q') { scanf("%d%d",&l,&r); printf("%d\n",query(1,l,r)); }else if(cmd[0] == 'A') { scanf("%d%d",&x,&v); modify(1,x,v); }else if(cmd[0] == 'S') { scanf("%d%d",&x,&v); modify(1,x, -v); }else if(cmd[0] == 'E') { break; } } } return 0; }