在原来的 区间加 和 区间求和 基础上,添加了 区间乘 和 区间求每个数的平方的和
#include <bits/stdc++.h>
#define ll long long
#define maxn 100005
#define mod 998244353
#define reg register int
#define ivoid inline void
int n,q,opt,x,y,z,a[maxn];
struct xds
{
int l,r;
ll sum1,sum2;
int laz1,laz2;
}t[4*maxn];
ivoid down(int p)
{
t[p*2].laz1+= t[p].laz1; t[p*2+1].laz1+= t[p].laz1;
t[p*2].laz2+= t[p].laz2; t[p*2+1].laz2+= t[p].laz2;
t[p].laz1= 0; t[p].laz2= 1;
return;
}
int pd(int p)
{
if(t[p].laz1!=0 || t[p].laz2!=1)
return 1;
return 0;
}
ivoid build(int p,int l,int r)
{
t[p].l=l; t[p].r=r; t[p].laz2=1;
if(l==r)
{
t[p].sum1=a[l]; t[p].sum2=a[l]*a[l]%mod;
return;
}
int mid=(l+r)/2;
build(p*2,l,mid); build(p*2+1,mid+1,r);
t[p].sum1=(t[p*2].sum1 + t[p*2+1].sum1)%mod;
t[p].sum2=(t[p*2].sum2 + t[p*2+1].sum2)%mod;
return;
}
ivoid plu(int p,int x,int y,int z)//区间加
{
if(x<=t[p].l && t[p].r<=y)
{
t[p].sum2+= (2*t[p].sum1*z + (t[p].r-t[p].l+1)*z*z)%mod;
t[p].sum1+= z*(t[p].r - t[p].l +1);
t[p].laz1+= z;
return;
}
if(t[p].l<=x && y<=t[p].r && pd(p)==1)
down(p);
int mid=(t[p].l + t[p].r)/2;
if(x<=mid) plu(p*2,x,y,z);
if(mid+1<=y) plu(p*2+1,x,y,z);
t[p].sum1=(t[p*2].sum1 + t[p*2+1].sum1)%mod;
t[p].sum2=(t[p*2].sum2 + t[p*2+1].sum2)%mod;
return;
}
ivoid mul(int p,int x,int y,int z)//区间乘
{
if(x<=t[p].l && t[p].r<=y)
{
t[p].sum2= ((t[p].sum2*z %mod) *z)%mod;
t[p].sum1= t[p].sum1*z %mod;
t[p].laz1*= z;
t[p].laz2*= z;
return;
}
if(t[p].l<=x && y<=t[p].r && pd(p)==1)
down(p);
int mid=(t[p].l + t[p].r)/2;
if(x<=mid) mul(p*2,x,y,z);
if(mid+1<=y) mul(p*2+1,x,y,z);
t[p].sum1=(t[p*2].sum1 + t[p*2+1].sum1)%mod;
t[p].sum2=(t[p*2].sum2 + t[p*2+1].sum2)%mod;
return;
}
ll query1(int p,int x,int y)//数值和
{
if(x<=t[p].l && t[p].r<=y)
return t[p].sum1;
if(t[p].l<=x && y<=t[p].r && pd(p)==1)
down(p);
ll ans=0;
int mid=(t[p].l + t[p].r)/2;
if(x<=mid) ans= (ans+ query1(p*2,x,y)) %mod;
if(mid+1<=y) ans= (ans+ query1(p*2+1,x,y)) %mod;
return ans;
}
ll query2(int p,int x,int y)//平方和
{
if(x<=t[p].l && t[p].r<=y)
return t[p].sum2;
if(t[p].l<=x && y<=t[p].r && pd(p)==1)
down(p);
ll ans=0;
int mid=(t[p].l + t[p].r)/2;
if(x<=mid) ans= (ans+ query2(p*2,x,y)) %mod;
if(mid+1<=y) ans= (ans+ query2(p*2+1,x,y)) %mod;
return ans;
}
int main()
{
scanf("%d %d",&n,&q);
for(reg i=1;i<=n;i++)
scanf("%d",&a[i]);
build(1,1,n);
t[0].laz2= 1;
while(q>0)
{
q--;
scanf("%d",&opt);
scanf("%d %d",&x,&y);
switch(opt)
{
case 1:
scanf("%d",&z);
plu(1,x,y,z);//区间加
break;
case 2:
scanf("%d",&z);
mul(1,x,y,z);//区间乘
break;
case 3:
printf("%lld\n",query1(1,x,y));//数值和
break;
case 4:
printf("%lld\n",query2(1,x,y));//平方和
break;
}
}
}
```c++