线段树(成段更新) 之 poj 3468 A Simple Problem with Integers
// [7/29/2014 Sjm] /* 线段树称断更新。。。 关键lazy思想,保存增量,更新时只更新到某一段,不再向下更新,待再次更新或查询到此段时,对其子节点进行更新。。 */
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstring> 5 #include <string> 6 using namespace std; 7 typedef __int64 int64; 8 #define lson l, m, rt<<1 9 #define rson m+1, r, rt<<1 | 1 10 #define GetMid(l, r) l+((r-l)>>1) 11 12 const int MAX_N = 100005; 13 int N, Q; 14 int64 Sum[MAX_N << 2], Mark[MAX_N << 2]; 15 16 void PushUp(int rt) { Sum[rt] = Sum[rt << 1] + Sum[rt << 1 | 1]; } 17 18 void PushDown(int rt, int len) { 19 if (Mark[rt]) { 20 Mark[rt << 1] += Mark[rt]; 21 Mark[rt << 1 | 1] += Mark[rt]; 22 Sum[rt << 1] += (len - (len >> 1))*Mark[rt]; 23 Sum[rt << 1 | 1] += (len >> 1)*Mark[rt]; 24 Mark[rt] = 0; 25 } 26 } 27 28 void Build(int l, int r, int rt) { 29 Mark[rt] = 0; 30 if (l == r) { scanf("%I64d", &Sum[rt]); return; } 31 int m = GetMid(l, r); 32 Build(lson); 33 Build(rson); 34 PushUp(rt); 35 } 36 37 void Update(int L, int R, int val, int l, int r, int rt) { 38 if (L <= l && r <= R) { 39 Sum[rt] += ((r - l + 1)*val); 40 Mark[rt] += val; 41 return; 42 } 43 PushDown(rt, (r - l + 1)); 44 int m = GetMid(l, r); 45 if (L <= m) Update(L, R, val, lson); 46 if (m < R) Update(L, R, val, rson); 47 PushUp(rt); 48 } 49 50 int64 Query(int L, int R, int l, int r, int rt) { 51 if (L <= l && r <= R) { 52 return Sum[rt]; 53 } 54 PushDown(rt, (r - l + 1)); 55 int64 ans = 0; 56 int m = GetMid(l, r); 57 if (L <= m) ans += Query(L, R, lson); 58 if (m < R) ans += Query(L, R, rson); 59 return ans; 60 } 61 62 int main() 63 { 64 //freopen("input.txt", "r", stdin); 65 //freopen("output.txt", "w", stdout); 66 while (~scanf("%d %d", &N, &Q)) { 67 Build(1, N, 1); 68 char str[2]; 69 int L, R, c; 70 while (Q--) { 71 scanf("%s %d %d", str, &L, &R); 72 if ('C' == str[0]) { 73 scanf("%d", &c); 74 if (0 == c) { continue; } 75 Update(L, R, c, 1, N, 1); 76 } 77 else { printf("%I64d\n", Query(L, R, 1, N, 1)); } 78 } 79 } 80 return 0; 81 }