区间修改+区间查询
#include<cstdio>
#define LL long long
using namespace std;
LL
a[100003],//原数列
tree[400003],//线段树
delta[400003];//标记
void update(int now)
{//用儿子们来更新自己
tree[now]=tree[now<<1]+tree[(now<<1)+1];
}
//update多多益善
void build(int now,int l,int r)
// 当前点编号 当前点左边界 当前点右边界
{//建树
if (l==r)
{84*30
tree[now]=a[l];
return;
}
int mid=(l+r)>>1;
build(now<<1,l,mid);//递归建左儿子
build((now<<1)+1,mid+1,r);//递归建右儿子
update(now);//更新一下
}
/*void point_change(int now,int l,int r,int x,int v)
{//点修改
if(l==r) {tree[now]+=v;return;}
int mid=(l+r)>>1;
if(x<=mid) point_change(now<<1,l,mid,x,v);
else point_change((now<<1)+1,mid+1,r,x,v);
update(now);
}*/
void pushdown(int l,int r,int mid,int now)
//当前点左边界 当前点右边界 当前点左右儿子分界 当前点编号
{//下传标记
//本题标记为还未加上的数
if (delta[now]!=0)//如果有未下传的标记
{
tree[now<<1]+=(mid-l+1)*delta[now];
//左儿子 加上 元素数*标记
delta[now<<1]+=delta[now];//标记传递
tree[(now<<1)+1]+=(r-mid)*delta[now];
//左儿子 加上 元素数*标记
delta[(now<<1)+1]+=delta[now];//标记传递
delta[now]=0;//标记清空
}
}
LL sum(int l,int r,int lrange,int rrange,int now)
//当前点左边界 当前点右边界 区间左边界 区间右边界 当前点编号
{//区间查询
if (lrange<=l && rrange>=r)//完全包含这段区间
return tree[now];//直接返回值
int mid=(l+r)>>1;LL ans=0;
pushdown(l,r,mid,now);//下传标记
if (mid>=lrange)//左儿子上有需查询的部分
ans+=sum(l,mid,lrange,rrange,now<<1);
if (mid<rrange)//右儿子上有需查询的部分
ans+=sum(mid+1,r,lrange,rrange,(now<<1)+1);
return ans;
}
void change(int l,int r,int lrange,int rrange,int now,int v)
//当前点左边界 当前点右边界 区间左边界 区间右边界 当前点编号 修改值
{//区间修改
if (lrange<=l && r<=rrange)
{//完全包含这段区间
tree[now]+=(r-l+1)*v;//加上 元素数*标记
delta[now]+=v;//做标记
return;//不用再递归
}
int mid=(l+r)>>1;
pushdown(l,r,mid,now);//先下传标记!
if(lrange<=mid)//左儿子上有需修改的部分
change(l,mid,lrange,rrange,now<<1,v);
if(rrange>mid)//右儿子上有需修改的部分
change(mid+1,r,lrange,rrange,(now<<1)+1,v);
update(now);//update多多益善
}
int main()
{
int n,m,i,l,r,k;
scanf("%d%d",&n,&m);
//该数列数字个数 操作总个数
for (i=1;i<=n;++i) scanf("%lld",&a[i]);
//读入原数列
build(1,1,n);//建树
for (i=1;i<=m;++i)
{
int t; scanf("%d",&t);//操作类型
if(t==1)
{//将区间[l,r]内每个数加上k
scanf("%d%d%d",&l,&r,&k);
change(1,n,l,r,1,k);
}
else
{//输出区间[l,r]的和
scanf("%d%d",&l,&r);
printf("%lld\n",sum(1,n,l,r,1));
}
}
return 0;
}