全裸的单点更新....
代码:
#include<cstdio> #include<cstring> #include<iostream> using namespace std; #define MAXN 50002 struct node { int mid, l, r; int v; }a[MAXN*4]; // 4倍? int n; void pushUp(int e) { a[e].v = a[e<<1].v+a[e<<1|1].v; } void build(int l, int r, int e) //CALL: build(1, n, 1) { a[e].l=l, a[e].r=r; if(l==r) { scanf("%d", &a[e].v); } else { a[e].mid = (l+r)>>1; build(l, a[e].mid, e<<1); build(a[e].mid+1, r, e<<1|1); pushUp(e); //以前的做法是先init空的树,再insert数据。现在没有insert了。所以要pushUp } } void update(int p, int add, int l, int r, int e) //单点更新,CALL: update(p, add, 1, n, 1); { if(l==r) { a[e].v+=add; } else { if(p<=a[e].mid) update(p, add, l, a[e].mid, e<<1); else update(p, add, a[e].mid+1, r, e<<1|1); pushUp(e); //以前的做法是,随着update,每个经过的区间都先add } } int query(int L, int R, int l, int r, int e) //查询[L, R],CALL:query(L, R, 1, n, 1); { int ret=0; if(L<=l && r<=R) //当前区间完全包含所查区间 { ret+=a[e].v; } else // l L R r { if(L<=a[e].mid) ret+=query(L, R, l, a[e].mid, e<<1); // L<= mid if(a[e].mid<R) ret+=query(L, R, a[e].mid+1, r, e<<1|1); //mid<R , 没有=号 } return ret; } int main() { int t; scanf("%d", &t); for(int i=0; i<t; i++) { printf("Case %d:\n", i+1); scanf("%d", &n); build(1, n, 1); for(char buf[10]; scanf("%s", &buf) && buf[0]!='E'; ) { int a, b; scanf("%d%d", &a, &b); if(buf[0]=='Q') { printf("%d\n", query(a, b, 1, n, 1)); } else if(buf[0]=='A') { update(a, b, 1, n, 1); } else if(buf[0]=='S') { update(a, -b, 1, n, 1); } } } }