【代码】
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define f(i,n) for(int i=1;i<=(n);i++)
#define ll long long
#define INF 1<<30
#define N 100010
int read()
{
int x=0,f=1;char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while( isdigit(c)){x=x*10+c-'0';c=getchar();}
return x*f;
}
int a[N];
ll maxn[3*N],sum[3*N],minn[3*N],sumf[3*N],tag[3*N];
int n,q,z;
//向上传递
void pushup(int o,int l,int r)
{
int lo=2*o,ro=2*o+1,m=(l+r)>>1;
sum[o]=sum[lo]+sum[ro];
maxn[o]=max(maxn[lo],maxn[ro]);
minn[o]=min(minn[lo],minn[ro]);
sumf[o]=sumf[lo]+sumf[ro];
}
//定义线段树
void dingyi(int o,int l,int r)
{
if(l==r)
{
sum[o]=maxn[o]=minn[o]=a[l];
sumf[o]=a[l]*a[l];
return;
}
int lo=2*o,ro=2*o+1,m=(l+r)>>1;
dingyi(lo,l,m);
dingyi(ro,m+1,r);
pushup(o,l,r);
}
//向下传递tag
void pushdown(int o,int l,int r)
{
if(l==r)return;
int lo=2*o,ro=2*o+1,m=(l+r)>>1;
if(tag[o])
{
tag[lo]+=tag[o];
tag[ro]+=tag[o];
sumf[lo]+=(ll)(m-l+1)*tag[o]*tag[o]+(ll)2*tag[o]*sum[lo];
sumf[ro]+=(ll)(r-m)*tag[o]*tag[o]+(ll)2*tag[o]*sum[ro];
sum[lo]+=(ll)(m-l+1)*tag[o];
sum[ro]+=(ll)(r-m)*tag[o];
maxn[lo]+=tag[o];
maxn[ro]+=tag[o];
minn[lo]+=tag[o];
minn[ro]+=tag[o];
}
tag[o]=0;
}
//区间加
int addl,addr,addi;
void add(int o,int l,int r)
{
if(l>=addl&&r<=addr)
{
sumf[o]+=(ll)(r-l+1)*addi*addi+2ll*addi*sum[o];
sum[o]+=(ll)(r-l+1)*addi;
maxn[o]+=addi;
minn[o]+=addi;
tag[o]+=addi;
return;
}
pushdown(o,l,r);
int lo=2*o,ro=2*o+1,m=(l+r)>>1;
if(addl<=m)add(lo,l,m);
if(addr>m)add(ro,m+1,r);
pushup(o,l,r);
}
//区间查询
ll qsum=0,qsumf=0;
int ql,qr;
void query(int o,int l,int r)
{
if(l>=ql&&r<=qr)
{
qsum+=sum[o];
qsumf+=sumf[o];
return;
}
int lo=2*o,ro=2*o+1,m=(l+r)>>1;
pushdown(o,l,r);
if(ql<=m)query(lo,l,m);
if(qr>m)query(ro,m+1,r);
pushup(o,l,r);
}
int main()
{
n=read();
q=read();
f(i,n)a[i]=read();
dingyi(1,1,n);
f(i,q)
{
z=read();
if(z==1)
{
addl=read();
addr=read();
scanf("%lld",&addi);
if(addi==0)continue;
add(1,1,n);
}
if(z==2)
{
ql=read();
qr=read();
qsum=0;
qsumf=0;
query(1,1,n);
}
}
}