如题,已知一个数列,你需要进行下面两种操作:
1.将某区间每一个数加上x
2.将某区间每一个数乘上x
3.求出某区间每一个数的和
第一行包含三个整数N、M、P,分别表示该数列数字的个数、操作的总个数和模数。
第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。
接下来M行每行包含3或4个整数,表示一个操作,具体如下:
操作1: 格式:1 x y k 含义:将区间[x,y]内每个数乘上k
操作2: 格式:2 x y k 含义:将区间[x,y]内每个数加上k
操作3: 格式:3 x y 含义:输出区间[x,y]内每个数的和对P取模所得的结果
输出格式:
输出包含若干行整数,即为所有操作3的结果。
5 5 38 1 5 4 2 3 2 1 4 1 3 2 5 1 2 4 2 2 3 5 5 3 1 4
17 2
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=8,M<=10
对于70%的数据:N<=1000,M<=10000
对于100%的数据:N<=100000,M<=100000
双lazytag线段树板子。真的难打。代码能力还是太弱。
#include
#define ll long long
using namespace std;
ll sum[400001],n,m,p,lazyc[400001],lazyj[400001],a[100001];
void build(int x,int y,int num)
{
if (x==y) {sum[num]=a[x];return;}
int mid=(x+y)/2;
build(x,mid,num*2);build(mid+1,y,num*2+1);
sum[num]=sum[num*2]+sum[num*2+1];
}
void pushdown(int num,int l,int r)
{
if (lazyc[num]!=1)
{
lazyc[num*2]=(lazyc[num*2]*lazyc[num])%p;
lazyj[num*2]=(lazyj[num*2]*lazyc[num])%p;
sum[num*2]=(sum[num*2]*lazyc[num])%p;
lazyc[num*2+1]=(lazyc[num*2+1]*lazyc[num])%p;lazyj[num*2+1]=(lazyj[num*2+1]*lazyc[num])%p;sum[num*2+1]=(sum[num*2+1]*lazyc[num])%p;
lazyc[num]=1;
}
int mid=(l+r)/2;
if (lazyj[num]!=0)
{
lazyj[num*2]=(lazyj[num*2]+lazyj[num])%p;sum[num*2]=(sum[num*2]+lazyj[num]*(mid-l+1))%p;
lazyj[num*2+1]=(lazyj[num*2+1]+lazyj[num])%p;sum[num*2+1]=(sum[num*2+1]+lazyj[num]*(r-mid))%p;
lazyj[num]=0;
}
}
void change(int num,int L,int R,int l,int r,int k,int bj)
{
if (l<=L&&r>=R)
{
if (bj==1) lazyc[num]=lazyc[num]*k%p,lazyj[num]=lazyj[num]*k%p,sum[num]=sum[num]*k%p;
else lazyj[num]=(lazyj[num]+k)%p,sum[num]=(sum[num]+(R-L+1)*k)%p;return;
}
pushdown(num,L,R);
int mid=(L+R)/2;
if (l<=mid) change(num*2,L,mid,l,r,k,bj);
if (r>=mid+1) change(num*2+1,mid+1,R,l,r,k,bj);
sum[num]=sum[num*2]+sum[num*2+1];
}
ll find(int num,int l,int r,int L,int R)
{
if (l>=L&&r<=R) return sum[num];
pushdown(num,l,r);
ll s=0;int mid=(l+r)/2;
if (L<=mid) s=(s+find(num*2,l,mid,L,R))%p;
if (mid+1<=R) s=(s+find(num*2+1,mid+1,r,L,R))%p;
return s;
}
int main()
{
scanf("%d%d%d",&n,&m,&p);
for (int i=1;i<=n;i++)scanf("%d",&a[i]);
for (int i=1;i<=4*n;i++)lazyc[i]=1;
build(1,n,1);
for (int i=1;i<=m;i++)
{
int x,y,z,k;
scanf("%d",&x);
if (x==1)
{
scanf("%d%d%d",&y,&z,&k);
change(1,1,n,y,z,k,1);
}
if (x==2)
{
scanf("%d%d%d",&y,&z,&k);
change(1,1,n,y,z,k,2);
}
if (x==3)
{
scanf("%d%d",&y,&z);
printf("%d\n",find(1,1,n,y,z));
}
}
return 0;
}