/*
*
* 带lazy机制的线段树维护区间信息
*/
#include <stdio.h>
#include <algorithm>
using namespace std;
struct Data {
long long sum; // 区间总和
long long lazy; // lazy标记数值
};
struct Node {
int start; // 区间开始位置
int end; // 区间结束位置
Data data; // 区间数据
}__global_nodes[100005*4] ;
class SegmentTree {
private:
Node* __nodes; // 节点数组
int __n; // 区间为0到n-1
// 下沉lazy标记
void __push_down_lazy(int node_idx) {
Node& node = __nodes[node_idx];
int mid = (node.start + node.end) >> 1;
int left_idx = node_idx*2+1, right_idx = node_idx*2+2;
if (node.data.lazy != 0) {
// 下沉lazy标记
__nodes[left_idx].data.sum += (mid-node.start+1) * node.data.lazy;
__nodes[left_idx].data.lazy += node.data.lazy;
__nodes[right_idx].data.sum += (node.end - mid) * node.data.lazy;
__nodes[right_idx].data.lazy += node.data.lazy;
node.data.lazy = 0;
}
}
// 更新单个位置的数值
void __update_single(int node_idx, int pos, long long val) {
Node& node = __nodes[node_idx];
if (node.start == node.end) {
node.data.sum += val;
return;
}
__push_down_lazy(node_idx);
int mid = (node.start + node.end) >> 1;
if (pos <= mid) {
__update_single(node_idx*2+1, pos, val);
} else {
__update_single(node_idx*2+2, pos, val);
}
node.data.sum = __nodes[node_idx*2+1].data.sum + __nodes[node_idx*2+2].data.sum;
}
// 更新区间数据
void __update_range(int node_idx, int start, int end, long long val) {
Node& node = __nodes[node_idx];
if (node.start == start && node.end == end) {
node.data.sum += val * (node.end - node.start + 1);
node.data.lazy += val;
return;
}
__push_down_lazy(node_idx);
int mid = (node.start + node.end) >> 1;
if (end <= mid) {
__update_range(node_idx*2+1, start, end, val);
} else if (start >= mid + 1) {
__update_range(node_idx*2+2, start, end, val);
} else {
__update_range(node_idx*2+1, start, mid, val);
__update_range(node_idx*2+2, mid+1, end, val);
}
node.data.sum = __nodes[node_idx*2+1].data.sum + __nodes[node_idx*2+2].data.sum;
}
// 获取区间统计信息
long long __get_val(int node_idx, int start, int end) {
Node& node = __nodes[node_idx];
if (node.start == start && node.end == end) {
return node.data.sum;
}
__push_down_lazy(node_idx);
int mid = (node.start + node.end) >> 1;
if (end <= mid) {
return __get_val(node_idx*2+1, start, end);
} else if (start >= mid+1) {
return __get_val(node_idx*2+2, start, end);
} else {
long long val1 = __get_val(node_idx*2+1, start, mid);
long long val2 = __get_val(node_idx*2+2, mid+1, end);
return val1 + val2;
}
}
public:
SegmentTree(int n, Node* pnodes) {
__n = n;
__nodes = pnodes;
__nodes[0] = {0, n-1, 0};
for (int i = 0; i < __n << 2; i++) {
if (__nodes[i].start == __nodes[i].end and __nodes[i].end == __n-1) {
break;
}
int mid = (__nodes[i].start + __nodes[i].end) / 2;
__nodes[i*2+1] = {__nodes[i].start, mid, {0, 0}};
__nodes[i*2+2] = {mid+1, __nodes[i].end, {0, 0}};
}
}
// 更新单个数据接口
void update_single(int pos, long long val) {
__update_single(0, pos, val);
}
// 更新区间数据接口
void update_range(int start, int end, long long val) {
__update_range(0, start, end, val);
}
// 获取区间统计数据接口
long long get_val(int start, int end) {
return __get_val(0, start, end);
}
};
int main(void) {
//freopen("/Users/grh/Programming/CLionProjects/Test/data.txt", "r", stdin);
int n, m;
long long val;
int start, end;
scanf("%d %d", &n, &m);
SegmentTree tree(n, __global_nodes);
for (int i = 0; i < n; i++) {
scanf("%lld", &val);
tree.update_single(i, val);
}
char c[2];
for (int i = 0; i < m; i++) {
scanf("%s", c);
if (c[0] == 'Q') {
scanf("%d %d", &start, &end);
printf("%lld\n", tree.get_val(start-1, end-1));
} else {
scanf("%d %d %lld", &start, &end, &val);
tree.update_range(start-1, end-1, val);
}
}
return 0;
}