rt,把找到的能模的地方都模了,开了unsigned ll(开LL也不能过),因为是动态开点所以空间只开了两倍(试过开四倍了,过不了……)
感觉自己写得很对但实际上只有30pts……
#include<bits/stdc++.h>
#define N 100005
#define int unsigned long long
using namespace std;
int n,mod,t,a[N],st,bh;
struct tree{
int l,r,sum,add,mul;
}tr[N<<2];
void build(int&,int,int),add(int,int,int,int,int,int),mul(int,int,int,int,int,int),push(int,int,int);
int sum(int,int,int,int,int);
signed main(){
scanf("%llu%llu%llu",&n,&t,&mod);
for(int i=1;i<=n;++i)
scanf("%llu",&a[i]);
build(st,1,n);
while(t--){
int op,x,y,k;
scanf("%llu%llu%llu",&op,&x,&y);
if(op<3){
scanf("%llu",&k);
if(op&1)
mul(1,1,n,x,y,k);
else
add(1,1,n,x,y,k);
}
else
printf("%llu\n",sum(1,1,n,x,y));
}
return 0;
}
void build(int &no,int l,int r){
if(!no) no=++bh;
if(l==r){
tr[no].sum=a[l],tr[no].mul=1;
return ;
}
int mi=l+r>>1;
build(tr[no].l,l,mi),build(tr[no].r,mi+1,r);
tr[no].sum=(tr[tr[no].l].sum+tr[tr[no].r].sum)%mod;
tr[no].mul=1;
}
void add(int no,int l,int r,int st,int en,int k){
int lc=tr[no].l,rc=tr[no].r,mi=l+r>>1;
if(l>=st&&r<=en){
tr[no].add+=k,tr[no].add%=mod;
tr[no].sum+=k*(r-l+1)%mod,tr[no].sum%=mod;
return ;
}
push(no,l,r);
if(st<=mi)
add(lc,l,mi,st,en,k);
if(en>mi)
add(rc,mi+1,r,st,en,k);
tr[no].sum=(tr[lc].sum+tr[rc].sum)%mod;
}
void mul(int no,int l,int r,int st,int en,int k){
int mi=l+r>>1,lc=tr[no].l,rc=tr[no].r;
if(l>=st&&r<=en){
tr[no].sum*=k,tr[no].sum%=mod;
tr[no].add*=k,tr[no].add%=mod;
tr[no].mul*=k,tr[no].mul%=mod;
return ;
}
push(no,l,r);
if(en>mi)
mul(rc,mi+1,r,st,en,k);
if(st<=mi)
mul(lc,l,mi,st,en,k);
tr[no].sum=(tr[rc].sum+tr[lc].sum)%mod;
}
int sum(int no,int l,int r,int st,int en){
int lc=tr[no].l,rc=tr[no].r,mi=l+r>>1;
if(l>=st&&r<=en)
return tr[no].sum;
push(no,l,r);
int ans=0;
if(st<=mi)
ans=sum(lc,l,mi,st,en);
if(en>mi)
ans+=sum(rc,mi+1,r,st,en),ans%=mod;
return ans%mod;
}
void push(int no,int l,int r){
int ad=tr[no].add,mu=tr[no].mul,lc=tr[no].l,rc=tr[no].r,mi=l+r>>1;
tr[no].add=0,tr[no].mul=1;
if(mu>1){
tr[lc].mul*=mu,tr[lc].mul%=mod;
tr[lc].add*=mu,tr[lc].add%=mod;
tr[lc].sum*=mu,tr[lc].sum%=mod;
tr[rc].mul*=mu,tr[rc].mul%=mod;
tr[rc].add*=mu,tr[rc].add%=mod;
tr[rc].sum*=mu,tr[rc].sum%=mod;
}
if(ad){
tr[lc].sum+=ad*(mi-l+1)%mod,tr[lc].sum%=mod;
tr[rc].sum+=ad*(r-mi)%mod,tr[rc].sum%=mod;
tr[lc].add+=ad,tr[lc].add%=mod;
tr[rc].add+=ad,tr[rc].add%=mod;
}
}