/*
还是老老实实的先用线段树来解决吧
区间和,区间更新
对于区间更新,这个如果更新到底的话,比较耗时,所以我新增了递增量。这样如果区间刚好和更新区域一样的话,就不要往下去了。只保存递增量
但是区间和的时候,就要有点变换了。出了拿出区间的和(已保存),还要计算从父节点过来的递增量。这个递增量和孩子节点的递增量是可以相加的
这样,区间和的复杂度没有增加,区间更新的复杂度小了点。
这样的时间大概是 1500ms
*/
// include file
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <ctime>
#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <bitset>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <set>
#include <list>
#include <functional>
using namespace std;
// typedef
typedef __int64 LL;
//
#define read freopen("in.txt","r",stdin)
#define write freopen("out.txt","w",stdout)
#define Z(a) (a<<1)
#define Y(a) (a>>1)
const double eps = 1e-6;
const double INFf = 1e100;
const int INFi = 1000000000;
const LL INFll = (LL)1<<62;
const double Pi = acos(-1.0);
template<class T> inline T sqr(T a){return a*a;}
template<class T> inline T TMAX(T x,T y)
{
if(x>y) return x;
return y;
}
template<class T> inline T TMIN(T x,T y)
{
if(x<y) return x;
return y;
}
template<class T> inline T MMAX(T x,T y,T z)
{
return TMAX(TMAX(x,y),z);
}
template<class T> inline T MMIN(T x,T y,T z)
{
return TMIN(TMIN(x,y),z);
}
template<class T> inline void SWAP(T &x,T &y)
{
T t = x;
x = y;
y = t;
}
// code begin
int N,M;
LL data[100010];
struct seg_tree_node
{
LL left,right; //左右儿子
LL sum; //和
LL dz;
};
seg_tree_node mem[250000];
LL buildSegtree(LL l,LL r,int dx=1)
{
mem[dx].left = l;
mem[dx].right = r;
mem[dx].dz = 0;
if(l==r)
{
return mem[dx].sum = data[l];
}
LL z = buildSegtree(l,Y(l+r),Z(dx));
LL y = buildSegtree(Y(l+r)+1,r,Z(dx)+1);
return mem[dx].sum = (z+y);
}
void update(LL l,LL r,LL c,int dx=1)
{
if( mem[dx].left==l && mem[dx].right == r)
{
mem[dx].dz += c;
return ;
}
if(mem[dx].left==mem[dx].right)
{//到达根节点
mem[dx].sum += c;
return;
}
mem[dx].sum += (r-l+1)*c;
int zson = Z(dx),yson = Z(dx)+1;
if( l>mem[zson].right )
{//右儿子
update(l,r,c,yson);
}
else if( r<mem[yson].left )
{//左儿子
update(l,r,c,zson);
}
else
{
update(l,mem[zson].right,c,zson);
update(mem[yson].left,r,c,yson);
}
}
LL query(LL l,LL r,int dx=1,LL dz = 0)
{
if(mem[dx].left==l && mem[dx].right==r)
{
return mem[dx].sum + (mem[dx].dz+dz)*(r-l+1);
}
int zson = Z(dx),yson = Z(dx)+1;
if( l>mem[zson].right )
{//右
//printf("right\n");
return query(l,r,yson,dz+mem[dx].dz);
}
else if( r<mem[yson].left )
{//左
//printf("left\n");
return query(l,r,zson,dz+mem[dx].dz);
}
else
{//分
//printf("lr\n");
return query(l,mem[zson].right,zson,dz+mem[dx].dz) + query(mem[yson].left,r,yson,dz+mem[dx].dz);
}
}
int main()
{
read;
write;
char cmd[3];
LL a,b,c;
while(scanf("%d %d",&N,&M)==2)
{
for(int i=1;i<=N;i++)
{
scanf("%I64d",data+i);
}
buildSegtree(1,N);
while(M--)
{
scanf("%s",cmd);
switch(cmd[0])
{
case 'C':
//
scanf("%I64d %I64d %I64d",&a,&b,&c);
update(a,b,c);
break;
case 'Q':
// 查询
scanf("%I64d %I64d",&a,&b);
printf("%I64d\n",query(a,b) );
break;
default:
break;
}
}
}
return 0;
}