【BZOJ 1798】[Ahoi2009]Seq 维护序列seq
乘法和加法可以都保留 加个小处理!
#include <iostream>
#include <cstdio>
#include <cstring>
#define MAXN 100000
#define LL long long
LL a[MAXN*4],c[MAXN*4],j[MAXN*4],num[MAXN*4];
LL n,p,m;
void Build(int now,int L,int R)
{
c[now]=1;
if(L==R) {a[now]=num[L];return;}
int mid=(L+R)/2;
Build(now*2,L,mid);
Build(now*2+1,mid+1,R);
a[now]=a[now*2]+a[now*2+1];
}
void Pushdown(int now,int L,int R)
{
int mid=(L+R)/2;
if(L!=R)
{
c[now*2]*=c[now]; a[now*2]*=c[now];
c[now*2+1]*=c[now]; a[now*2+1]*=c[now];
j[now*2]=j[now*2]*c[now]+j[now]; a[now*2]+=(mid-L+1)*j[now];
j[now*2+1]=j[now*2+1]*c[now]+j[now]; a[now*2+1]+=(R-mid)*j[now];
c[now*2]%=p;
c[now*2+1]%=p;
j[now*2]%=p;
j[now*2+1]%=p;
a[now*2]%=p;
a[now*2+1]%=p;
}
c[now]=1;j[now]=0;
}
void Change(int now,int L,int R,int s,int t,int cc,int jj)
{
if(s<=L&&R<=t) {c[now]*=cc;c[now]%=p;j[now]=(j[now]*cc+jj)%p;a[now]*=cc;a[now]+=(R-L+1)*jj;a[now]%=p;return;}
Pushdown(now,L,R);
int mid=(L+R)/2;
if(t<=mid) Change(now*2,L,mid,s,t,cc,jj);
else if(s>=mid+1) Change(now*2+1,mid+1,R,s,t,cc,jj);
else Change(now*2,L,mid,s,t,cc,jj),Change(now*2+1,mid+1,R,s,t,cc,jj);
a[now]=(a[now*2]+a[now*2+1])%p;
}
int Query(int now,int L,int R,int s,int t)
{
if(s<=L&&R<=t) return a[now];
Pushdown(now,L,R);
int mid=(L+R)/2;
if(t<=mid) return Query(now*2,L,mid,s,t)%p;
else if(s>=mid+1) return Query(now*2+1,mid+1,R,s,t)%p;
else return (Query(now*2,L,mid,s,t)+Query(now*2+1,mid+1,R,s,t))%p;
}
inline int Read()
{
int ans=0;
char c=getchar();
while(c<'0'||c>'9') c=getchar();
while('0'<=c&&c<='9')ans=ans*10+c-'0',c=getchar();
return ans;
}
int main()
{
scanf("%lld %lld",&n,&p);
for(int i=1;i<=n;i++) num[i]=Read();
Build(1,1,n);
scanf("%lld",&m);
for(int opt,x,y,z,i=1;i<=m;i++)
{
opt=Read();
switch(opt)
{
case 1:x=Read(),y=Read(),z=Read();Change(1,1,n,x,y,z,0);break;
case 2:x=Read(),y=Read(),z=Read();Change(1,1,n,x,y,1,z);break;
case 3:x=Read();y=Read();printf("%d\n",Query(1,1,n,x,y));break;
}
}
return 0;
}