线段树求调
30分 对#1,#3,#4
#include<bits/stdc++.h>
#define int long long
using namespace std;
int a[100010],n,p;
struct stree{
long long l,r;
long long sum,tag,tagc=1;
}t[400010];
void build(int x,int l,int r){
t[x].l=l,t[x].r=r;
if(l==r){
t[x].sum=a[l];
return;
}
int mid=(l+r)>>1;
build(x*2,l,mid);
build(x*2+1,mid+1,r);
t[x].sum=t[x*2].sum+t[x*2+1].sum;
}
void down(int x){
if(t[x].tag){
t[x*2].sum=(t[x*2].sum*t[x].tagc%p+(t[x*2].r-t[x*2].l+1)*t[x].tag%p)%p;
t[x*2].sum%=p;
t[x*2+1].sum=(t[x*2+1].sum*t[x].tagc%p+(t[x*2+1].r-t[x*2+1].l+1)*t[x].tag%p)%p;
t[x*2+1].sum%=p;
t[x*2].tagc*=t[x].tagc;
t[x*2+1].tagc*=t[x].tagc;
t[x*2].tagc%=p;
t[x*2+1].tagc%=p;
t[x*2].tag*=t[x].tagc;
t[x*2+1].tag*=t[x].tagc;
t[x*2].tag%=p;
t[x*2+1].tag%=p;
t[x*2].tag+=t[x].tag;
t[x*2+1].tag+=t[x].tag;
t[x*2].tag%=p;
t[x*2+1].tag%=p;
t[x].tag=0;
t[x].tagc=1;
}
}
void change(int x,int l,int r,int a){
if(t[x].l>=l&&t[x].r<=r){
t[x].tag+=a%p;
t[x].tag%=p;
t[x].sum+=(t[x].r-t[x].l+1)*a%p;
t[x].sum%=p;
return;
}
if(t[x].l==t[x].r)return;
down(x);
int mid=(t[x].l+t[x].r)>>1;
if(mid>=l)change(x*2,l,r,a);
if(mid<r)change(x*2+1,l,r,a);
t[x].sum=(t[x*2].sum+t[x*2+1].sum)%p;
}
void changech(int x,int l,int r,int a){
if(t[x].l>=l&&t[x].r<=r){
t[x].tagc*=a;
t[x].tagc%=p;
t[x].tag*=a;
t[x].tag%=p;
t[x].sum*=a;
t[x].sum%=p;
return;
}
if(t[x].l==t[x].r)return;
down(x);
int mid=(t[x].l+t[x].r)>>1;
if(mid>=l)changech(x*2,l,r,a);
if(mid<r)changech(x*2+1,l,r,a);
t[x].sum=(t[x*2].sum+t[x*2+1].sum)%p;
}
long long ask(int x,int l,int r){
if(l<=t[x].l&&r>=t[x].r)return t[x].sum%p;
down(x);
int mid=(t[x].l+t[x].r)>>1;
long long sum=0;
if(mid>=l)sum+=ask(x*2,l,r)%p;
if(mid<r)sum+=ask(x*2+1,l,r)%p;
return sum;
}
signed main(){
//freopen("P3373_2.in","r",stdin);
//freopen("s.txt","w",stdout);
int n,m,k;
cin>>n>>m>>p;
for(int i=1;i<=n;i++){
cin>>a[i];
a[i]%=p;
}
build(1,1,n);
while(m--){
string op;
int a,b,c;
cin>>op>>a>>b;
if(op=="1"){
cin>>c;
changech(1,a,b,c);
}else if(op=="2"){
cin>>c;
change(1,a,b,c);
}else{
cout<<ask(1,a,b)%p<<endl;
}
}
return 0;
}