这题WA了好久,一直以为是lld和I64d的问题,后来发现是自己的pushdown函数写错了,说到底还是因为自己对线段树理解得不好。
因为是懒惰标记,所以只有在区间分开的时候才会将标记往下传递。更新和查询都要pushdown。
1 #include <cstdio> 2 3 typedef long long LL; 4 5 const int maxn = 100000 + 10; 6 7 int n, m, qL, qR, v; 8 LL sum[maxn << 2], add[maxn << 2]; 9 10 inline void maintain(int o) 11 { sum[o] = sum[o*2] + sum[o*2+1]; } 12 13 void build(int o, int L, int R) 14 { 15 if(L == R) { scanf("%I64d", &sum[o]); return; } 16 int M = (L + R) / 2; 17 build(o*2, L, M); 18 build(o*2+1, M+1, R); 19 maintain(o); 20 } 21 22 void pushdown(int o, int L, int R) 23 { 24 if(add[o]) 25 { 26 int lc = o*2, rc = o*2+1; 27 int M = (L + R) / 2; 28 add[lc] += add[o]; 29 add[rc] += add[o]; 30 sum[lc] += (LL) add[o] * (M - L + 1); 31 sum[rc] += (LL) add[o] * (R - M); 32 add[o] = 0; 33 } 34 } 35 36 void update(int o, int L, int R) 37 { 38 if(qL <= L && qR >= R) 39 { 40 add[o] += v; 41 sum[o] += (LL) v * (R - L + 1); 42 return; 43 } 44 int M = (L + R) / 2; 45 pushdown(o, L, R); 46 if(qL <= M) update(o*2, L, M); 47 if(qR > M) update(o*2+1, M+1, R); 48 maintain(o); 49 } 50 51 LL query(int o, int L, int R) 52 { 53 if(qL <= L && qR >= R) return sum[o]; 54 pushdown(o, L, R); 55 int M = (L + R) / 2; 56 LL ans = 0; 57 if(qL <= M) ans += query(o*2, L, M); 58 if(qR > M) ans += query(o*2+1, M+1, R); 59 return ans; 60 } 61 62 int main() 63 { 64 //freopen("in.txt", "r", stdin); 65 66 scanf("%d%d", &n, &m); 67 build(1, 1, n); 68 char op[10]; 69 while(m--) 70 { 71 scanf("%s", op); 72 if(op[0] == 'Q') 73 { 74 scanf("%d%d", &qL, &qR); 75 printf("%I64d\n", query(1, 1, n)); 76 } 77 else 78 { 79 scanf("%d%d%d", &qL, &qR, &v); 80 update(1, 1, n); 81 } 82 } 83 84 return 0; 85 }