线段树模板(求和)
相关知识详见:OI-WIKI
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,m,a[100010],d[400010],lz[400010];
ll mymax(ll pp,ll oo)
{
return pp>oo?pp:oo;
}
ll mymin(ll pp,ll oo)
{
return pp<oo?pp:oo;
}
void read(ll &z)
{
z=0;
ll ftr=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-') ftr=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
z=(z<<3)+(z<<1)+ch-'0';
ch=getchar();
}
z*=ftr;
}
void add(ll s,ll t,ll p) //建树
{
if(s==t)
{
d[p]=a[s];
return ;
}
ll l=(s+t)>>1;
ll r=l+1;
add(s,l,p*2),add(r,t,p*2+1);
d[p]=d[p*2]+d[p*2+1];
}
ll gs(ll l,ll r,ll s,ll t,ll p) //求和
{
if(l<=s&&r>=t)
{
return d[p];
}
ll mid=(s+t)>>1;
ll sum=0;
if(lz[p]>0)
{
d[p*2]+=lz[p]*(mid-s+1),d[p*2+1]+=lz[p]*(t-mid);
lz[p*2]+=lz[p],lz[p*2+1]+=lz[p];
lz[p]=0;
}
if(l<=mid)
{
sum+=gs(l,r,s,mid,p*2);
}
if(r>mid)
{
sum+=gs(l,r,mid+1,t,p*2+1);
}
return sum;
}
void gx(ll l,ll r,ll s,ll t,ll p,ll k) //更新
{
if(l<=s&&r>=t)
{
d[p]+=(t-s+1)*k;
lz[p]+=k;
return ;
}
ll mid=(s+t)>>1;
if(lz[p]>0&&s!=t)
{
d[p*2]+=lz[p]*(mid-s+1),d[p*2+1]+=lz[p]*(t-mid);
lz[p*2]+=lz[p],lz[p*2+1]+=lz[p];
lz[p]=0;
}
if(l<=mid)gx(l,r,s,mid,p*2,k);
if(mid<r)gx(l,r,mid+1,t,p*2+1,k);
d[p]=d[p*2]+d[p*2+1];
}
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
read(n),read(m);
for(int i=1;i<=n;i++)
{
read(a[i]);
}
add(1,n,1);
for(int i=1;i<=m;i++)
{
ll falg=0;
read(falg);
if(falg==1)
{
ll x,y,num;
read(x),read(y),read(num);
gx(x,y,1,n,1,num);
}
else
{
ll x,y;
read(x),read(y);
ll q;
q=gs(x,y,1,n,1);
printf("%lld\n",q);
}
}
return 0;
}