59
#include <stdio.h> #define maxn 50002 int arr[maxn]; struct Node{ int left, right, sum; } tree[maxn << 2]; char com[10]; void build(int left, int right, int rt) { tree[rt].left = left; tree[rt].right = right; if(left == right) { tree[rt].sum = arr[left]; return; } int mid = (left + right) >> 1; build(left, mid, rt << 1); build(mid + 1, right, rt << 1 | 1); tree[rt].sum = tree[rt<<1].sum + tree[rt<<1|1].sum; //回溯求sum } void update(int pos, int val, int rt) { if(tree[rt].left == tree[rt].right) { tree[rt].sum += val; return; } int mid = (tree[rt].left + tree[rt].right) >> 1; if(pos <= mid) update(pos, val, rt << 1); else update(pos, val, rt << 1 | 1); tree[rt].sum = tree[rt<<1].sum + tree[rt<<1|1].sum; //因为加上了val 所以还要回溯求sum } int query(int left, int right, int rt) { if(left == tree[rt].left && right == tree[rt].right) return tree[rt].sum; int mid = (tree[rt].left + tree[rt].right) >> 1; if(right <= mid) return query(left, right, rt << 1); else if(left > mid) return query(left, right, rt<<1|1); return query(left, mid, rt << 1) + //不符合上边的if else if是 return这个 query(mid+1, right, rt<<1|1); //也就是所要求的区间在mid的两侧 } int main() { int t, n, i, a, b; scanf("%d", &t); for(int cas = 1; cas <= t; ++cas) { scanf("%d", &n); for(i = 1; i <= n; ++i) scanf("%d", arr + i); build(1, n, 1); printf("Case %d:\n", cas); while(scanf("%s", com)) { if(com[0] == 'E') break; scanf("%d%d", &a, &b); if (com[0] == 'Q') printf("%d\n", query(a, b, 1)); else if (com[0] == 'A') update(a, b, 1); else if (com[0] == 'S') update(a, -b, 1); } } return 0; }
要真的是看不懂的话,那就自己模拟一次吧,模拟完了以后,你就会有很大的收获,因为你会很快的掌握这个算法。
说一点题外话,对于我们学习算法的来说,既然你想不出来怎么写了,那么你就要去看别人的,你要去研究别人的算法是怎么运行的,或者说就是模拟一遍,还不行的话就两遍,一直到你自己懂了为止,这样日积月累你就会有很大的收获的。
