https://cn.vjudge.net/contest/280153#problem/C
#include <iostream>
#include<cstdio>
#define ll long long
using namespace std;
const ll maxn = 1e5+1000;
struct node
{
ll l;
ll r;
ll sum;
ll lazy;
node()
{
lazy = 0;
sum = 0;
}
}Segtr[6*maxn];
ll num[maxn];
void pushdown(ll n);
void input(int N)
{
for(int i = 1;i <= N;i++)
{
cin>>num[i];
}
}
/*************建树函数****************.*/
void build(ll l, ll r, ll rt)//
{
Segtr[rt].l = l;
Segtr[rt].r = r;
ll mid = (l+r)/2;
Segtr[rt].lazy = 0;
Segtr[rt].sum = 0;
if(l == r)
{
Segtr[rt].sum = num[l];
return;
}
build(l, mid, 2*rt+1);
build(mid+1, r, 2*rt+2);
Segtr[rt].sum = Segtr[2*rt+1].sum+Segtr[2*rt+2].sum;
}
/**************更新函数**********************/
void update(ll l, ll r, ll rt,ll add)// 要修改 l,r区间边界 , rt树节点编号, add修改的值
{
ll L = Segtr[rt].l;
ll R = Segtr[rt].r;
if(Segtr[rt].lazy&&L!=R) pushdown(rt); //之前lazy 标记 就将他压给 子区间
if(L == l && R == r)// 如果 正好与 该区间吻合 , 修改, 并标记, 返回
{
Segtr[rt].sum+=(R-L+1)*add;
Segtr[rt].lazy+=add;//懒人标记
return;
}
ll mid = (L+R)/2;// (L+R)/2;
if(r <= mid)// 要修改的区间 在 mid 左面
{
update(l, r, rt*2+1, add);
}
else if(l > mid)
{
update(l, r, rt*2+2, add);
}
else
{
update(l , mid, rt*2+1, add);
update(mid+1, r, rt*2+2, add);
}
Segtr[rt].sum = Segtr[2*rt+1].sum+Segtr[2*rt+2].sum; // 父亲等于 修改后的两个子区间的值之和
}
/**************标记 下压 函数*****************/
void pushdown(ll rt)
{
/**修改 左区间的 值*/
Segtr[2*rt+1].sum += Segtr[rt].lazy*(Segtr[2*rt+1].r - Segtr[2*rt+1].l +1);
Segtr[2*rt+1].lazy += Segtr[rt].lazy; //给左子区间打上标记
/****修改 右区间 值****/
Segtr[2*rt+2].sum+=Segtr[rt].lazy*(Segtr[2*rt+2].r - Segtr[2*rt+2].l+1);
Segtr[2*rt+2].lazy += Segtr[rt].lazy;//给右子区间打上标记
Segtr[rt].sum = Segtr[2*rt+1].sum + Segtr[2*rt+2].sum;// 这里 可以删去
Segtr[rt].lazy = 0; // 取消父区间的标记
}
/********************询问函数**********************/
ll query(ll l, ll r, ll rt)
{
ll res = 0;
ll L = Segtr[rt].l;
ll R = Segtr[rt].r;
ll mid = (L+R)/2;
if(Segtr[rt].lazy&& L!= R) pushdown(rt);// L == R 表示 该节点是叶子节点 就不需要 继续往下压了
if(L == l && R == r)
{
return Segtr[rt].sum;
}
if(r <= mid)
{
res = query(l, r, 2*rt+1);
}
else if(l > mid)
{
res = query(l, r, 2*rt+2);
}
else
{
res+=query(l, mid, 2*rt+1);
res+=query(mid+1, r, 2*rt+2);
}
return res;
}
int main(void)
{
ll N, Q;
scanf("%lld %lld", &N, &Q);
input(N);
build(1, N, 0);
while(Q--)
{
char op[2];
ll l ,r, add;
scanf("%s %lld %lld", op, &l, &r);
if(op[0] == 'C')
{
scanf("%lld", &add);
update(l, r, 0, add);//
}
else
{
ll res = query(l, r, 0);
printf("%lld\n", res);
}
}
return 0;
}