/***********************************************題目大意:Q a b :查詢區間[a,b]的和;C a b x : 更新區間[a,b],區間所有值加上x;演算法思想:線段樹的成段更新--延遲更新;在區間查詢和更新的時候加入一個延遲節點;每次要在下次查詢或者更新到該區間時;再把節點的資訊傳遞到左右孩子的結點上;這樣更新大大減少了時間和空間上的開銷;演算法過程:每次更新並不需要更新到分葉節點;只需更新到相應的段就可以了,然後記錄個add;下次更新或者查詢的時候,如果要查到該段的子節點;就把add加到子節點上去,再將該add設為0;這樣查詢子區間的複雜度就是更新的複雜度;************************************************/#include<iostream>#include<cstring>#include<cstdlib>#include<cstdio>#include<climits>#include<algorithm>using namespace std;#define L l , m , u << 1#define R m + 1 , r , u << 1 | 1typedef long long LL;const int N = 111111;LL add[N<<2];LL sum[N<<2];void PushUp(int u)//把當前結點的資訊更新到父結點{ sum[u] = sum[u<<1] + sum[u<<1|1];}void PushDown(int u,int m)//把當前結點的資訊更新給兒子結點{ if (add[u]) { add[u<<1] += add[u]; add[u<<1|1] += add[u]; sum[u<<1] += add[u] * (m - (m >> 1)); sum[u<<1|1] += add[u] * (m >> 1); add[u] = 0; }}void build(int l,int r,int u){ add[u] = 0; if (l == r) { scanf("%lld",&sum[u]); return ; } int m = (l + r) >> 1; build(L); build(R); PushUp(u);}void update(int l1,int r1,int c,int l,int r,int u){ if (l1 <= l && r <= r1) { add[u] += c; sum[u] += (LL)c * (r - l + 1); return ; } PushDown(u , r - l + 1); int m = (l + r) >> 1; if (l1 <= m) update(l1 , r1 , c , L); if (m < r1) update(l1 , r1 , c , R); PushUp(u);}LL query(int l1,int r1,int l,int r,int u){ if (l1 <= l && r <= r1) { return sum[u]; } PushDown(u , r - l + 1); int m = (l + r) >> 1; LL res = 0; if (l1<= m) res += query(l1 , r1 , L); if (m < r1) res += query(l1 , r1 , R); return res;}int main(){ //freopen("C:\\Users\\Administrator\\Desktop\\kd.txt","r",stdin); int N , Q; scanf("%d%d",&N,&Q); build(1 , N , 1); while (Q--) { char op[2]; int a , b , c; scanf("%s",op); if (op[0] == 'Q') { scanf("%d%d",&a,&b); printf("%lld\n",query(a , b , 1 , N , 1)); } else { scanf("%d%d%d",&a,&b,&c); update(a , b , c , 1 , N , 1); } } return 0;}