区间加法和乘法,两个lazy数组同时维护。。。。。
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
const int maxn=100005;
ll mod;
struct Tree{
ll sum[maxn<<2],add[maxn<<2],mul[maxn<<2];
void Mod(int p){
sum[p]%=mod;
add[p]%=mod;
mul[p]%=mod;
}
void push_up(int p,int u,int v){
sum[p]=(sum[u]+sum[v])%mod;
}
void push_down(int p,int l,int r,int u,int v,int mid){
add[u]=add[u]*mul[p]+add[p];
add[v]=add[v]*mul[p]+add[p];
mul[u]*=mul[p];
mul[v]*=mul[p];
sum[u]=sum[u]*mul[p]+add[p]*(mid-l+1);
sum[v]=sum[v]*mul[p]+add[p]*(r-mid);
add[p]=0,mul[p]=1;
Mod(u),Mod(v);
}
void create_tree(int p,int l,int r){
mul[p]=1;
if(l==r){
scanf("%lld",&sum[p]);
sum[p]%=mod;
return;
}int mid=(l+r)>>1,u=p<<1,v=u+1;
create_tree(u,l,mid);
create_tree(v,mid+1,r);
push_up(p,u,v);
}
void update(int p,int l,int r,int L,int R,int w,int k){
if((l>=L)&&(r<=R)){
if(k==1){
sum[p]=sum[p]*w;
add[p]=add[p]*w;
mul[p]=mul[p]*w;
}else{
sum[p]=sum[p]+(r-l+1)*w;
add[p]=add[p]+w;
}Mod(p);
return;
}int mid=(l+r)>>1,u=p<<1,v=u+1;
push_down(p,l,r,u,v,mid);
if(L<=mid)update(u,l,mid,L,R,w,k);
if(R>mid)update(v,mid+1,r,L,R,w,k);
push_up(p,u,v);
}
int query(int p,int l,int r,int L,int R){
if((l>=L)&&(r<=R))
return sum[p];
int mid=(l+r)>>1,u=p<<1,v=u+1,res=0;
push_down(p,l,r,u,v,mid);
if(L<=mid)res+=query(u,l,mid,L,R);
if(R>mid)res+=query(v,mid+1,r,L,R);
push_up(p,u,v);
return res%mod;
}
}Tr;
int main(){
int n,m;
scanf("%d%lld",&n,&mod);
Tr.create_tree(1,1,n);
scanf("%d",&m);
while(m--){
int k,u,v,w;
scanf("%d%d%d",&k,&u,&v);
if(k==3)
printf("%d\n",Tr.query(1,1,n,u,v));
else{
scanf("%d",&w);
Tr.update(1,1,n,u,v,w,k);
}
}
return 0;
}