如果每次赋值都遍历到叶子节点,则赋值的复杂度变为O(N),因此赋值时深入到需要赋值的那个区间就应当停止,记录当前的增量,如果下次搜索时,根据需要向下传递这个增量,这样的复杂度就降下来了 #include <iostream> using namespace std; const int MAX_N = 100000; int A[MAX_N+5]; int N, Q; struct Node { int left; int right; __int64 sum; __int64 inc;//记录区间增量,虽然题目给的数据范围用int可以,但该死的用int就是WA } tree[3*MAX_N]; void createTree(int root, int l, int r) { if(l == r) { tree[root].left = l; tree[root].right = r; tree[root].sum = A[l]; tree[root].inc = 0; return; } createTree(root<<1, l, (l+r)>>1); createTree((root<<1)+1, (l+r>>1)+1, r); tree[root].left = l; tree[root].right = r; tree[root].sum = tree[root<<1].sum + tree[(root<<1)+1].sum; tree[root].inc = 0; } void add(int root, int a, int b, int c) { if(tree[root].left==a && tree[root].right==b) { tree[root].sum += (b-a+1)*c; tree[root].inc += c; return; } tree[root].sum += (b-a+1)*c;//注意此处不能少!!! int mid = tree[root].left + tree[root].right>>1; if(b <= mid) { add(root<<1, a, b, c); return; } if(a > mid) { add((root<<1)+1, a, b, c); return; } add(root<<1, a, mid, c); add((root<<1)+1, mid+1, b, c); } __int64 search(int root, int a, int b) { if(tree[root].left==a && tree[root].right==b) return tree[root].sum; int mid = tree[root].left + tree[root].right>>1; if(tree[root].inc)//此处更新子节点的sum { tree[root<<1].sum += (mid-tree[root].left+1)*tree[root].inc; tree[root<<1].inc += tree[root].inc; tree[(root<<1)+1].sum += (tree[root].right-mid)*tree[root].inc; tree[(root<<1)+1].inc += tree[root].inc; tree[root].inc = 0; } if(b <= mid) return search(root<<1, a, b); if(a > mid) return search((root<<1)+1, a, b); return search(root<<1, a, mid) + search((root<<1)+1, mid+1, b); } int main() { char opt; int a, b, c, i; while(~scanf("%d%d", &N, &Q)) { for(int i=1; i<=N; i++) scanf("%d", A+i); getchar(); createTree(1, 1, N); while(Q--) { scanf("%c", &opt); if(opt == 'Q') { scanf("%d%d", &a, &b); printf("%I64d/n", search(1, a, b)); } else if(opt == 'C') { scanf("%d%d%d", &a, &b, &c); add(1, a, b, c); } getchar(); } } return 0; }