#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
ll sum[N<<2] , add[N<<2];
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
struct Node//线段树结构
{
int l , r;
int mid()
{
return (l+r)>>1;
}
}tree[N<<2];
void PushUp(int rt)//更新父节点的值
{
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void PushDown(int rt , int m)//更新儿子节点的属性
{
if(add[rt])//检查是否有延迟标记
{
add[rt<<1] += add[rt];//将延迟标记传递给儿子节点
add[rt<<1|1] += add[rt];
sum[rt<<1] += add[rt]*(m-(m>>1));//更新儿子节点的sum值
sum[rt<<1|1] += add[rt]*(m>>1);
add[rt] = 0;
}
}
void build(int l , int r ,int rt)//建树
{
tree[rt].l = l;
tree[rt].r = r;
add[rt] = 0;
if(l == r)//最底层儿子(节点左区间=节点右区间)
{
scanf("%lld" , &sum[rt]);
return ;
}
int m = tree[rt].mid();
build(lson);
build(rson);
PushUp(rt);//向上更新sum的值
}
void update(int c ,int l , int r , int rt)//更新节点
{
if(tree[rt].l == l && tree[rt].r == r)
{
add[rt] += c;
sum[rt] += (ll)c*(r-l+1);
return ;//如果与更新区间重合,更新此节点后,不再往下更新
//如果不重合,便继续往下寻找。
}
if(tree[rt].l == tree[rt].r)
return ;
PushDown(rt, tree[rt].r-tree[rt].l+1);//更新此节点的两个儿子
int m = tree[rt].mid();
if(r <= m)
update(c, l, r, rt<<1);
else if(l > m)
update(c,l,r,rt<<1|1);
else
{
update(c,l,m,rt<<1);
update(c,m+1,r,rt<<1|1);
}
PushUp(rt);//更新第sum[rt]
}
ll Query(int l , int r , int rt)
{
if(l == tree[rt].l && r == tree[rt].r)
return sum[rt];
PushDown(rt, tree[rt].r-tree[rt].l+1);
int m = tree[rt].mid();
ll res = 0;
if(r <= m)
res += Query(l,r,rt<<1);
else if(l > m)
res += Query(l, r, rt<<1|1);
else
{
res += Query(l, m, rt<<1);
res += Query(m+1,r,rt<<1|1);
}
return res;
}
int main(void)
{
int n , m;
while(scanf("%d %d",&n ,&m)!=EOF)
{
build(1, n, 1);
while(m --)
{
char ch[2];
scanf("%s",ch);
int a , b ,c ;
if(ch[0] == 'Q')
{
scanf("%d %d",&a, &b);
printf("%lld\n",Query(a,b,1));
}
else
{
scanf("%d %d %d",&a ,&b ,&c);
update(c,a,b,1);
}
}
}
}