题目链接:POJ 3468 A Simple Problem with Integers
简单的线段树区间更新。
难点在于延迟更新的思想,简单说就是不要每次更新都更新到叶子节点,这样太消耗时间,所以每个节点都增加一个inc来记录增量的累加。当传参区间与当前节点区间相同时,改变该节点的inc,然后return,停止向下更新。
#include <iostream> #include <stdio.h> using namespace std; const int MAX_N = 100000 + 1000; const int MAX_M = MAX_N << 2; struct Node { int l,r; long long sum; long long inc; }; int arr[MAX_N]; Node node[MAX_M]; int n,q; void build(int l,int r,int i) { node[i].l = l; node[i].r = r; node[i].sum = 0; node[i].inc = 0; if(l == r) { node[i].sum = arr[l]; return; } int mid = (l + r) >> 1; build(l,mid,i << 1); build(mid + 1,r,i << 1 | 1); node[i].sum = node[i << 1].sum + node[i << 1 | 1].sum; } void add(int l,int r,int i,long long val) { if(node[i].l == l && node[i].r == r) { node[i].inc += val; return; } node[i].sum += (r - l + 1) * val; int mid = (node[i].l + node[i].r) >> 1; if(mid < l) add(l,r,i << 1 | 1,val); else if(mid >= r) add(l,r,i << 1,val); else { add(l,mid,i << 1,val); add(mid + 1,r,i << 1 | 1,val); } } long long query(int l,int r,int i) { if(node[i].l == l && node[i].r == r) { return node[i].sum + (node[i].r - node[i].l + 1) * node[i].inc; } node[i].sum += (node[i].r - node[i].l + 1) * node[i].inc; int mid = (node[i].l + node[i].r) >> 1; add(node[i].l,mid,i << 1,node[i].inc); add(mid + 1,node[i].r,i << 1 | 1,node[i].inc); node[i].inc = 0; if(mid < l) return query(l,r,i << 1 | 1); else if(mid >= r) return query(l,r,i << 1); else return query(l,mid,i << 1) + query(mid + 1,r,i << 1 | 1); } int main() { while(scanf("%d %d",&n,&q) != EOF) { for(int i = 1;i <= n;i++) scanf("%d",&arr[i]); build(1,n,1); char c[3]; int a,b; long long val; for(int i = 1;i <= q;i++) { scanf("%s",c); if(c[0] == 'Q') { scanf("%d %d",&a,&b); printf("%lld\n",query(a,b,1)); } else if(c[0] == 'C') { scanf("%d %d %lld",&a,&b,&val); add(a,b,1,val); } } } }