Code:
#include<bits/stdc++.h>
#pragma GCC optimise(2)
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
const int inf = 0x3f3f3f3f;
struct Node {
ll L,R;
ll sum,add_tag,mul_tag;
} tree[N*4];
ll n,m,p;
ll a[N];
void build(ll rt,ll L,ll R) {
if(L==R) {
tree[rt].sum = a[L];
tree[rt].L = tree[rt].R = L;
tree[rt].mul_tag = 1;
tree[rt].add_tag = 0;
return;
}
ll mid = (L+R) >> 1;
build(rt<<1,L,mid);
build(rt<<1|1,mid+1,R);
tree[rt] = {L,R,(tree[rt<<1].sum+tree[rt<<1|1].sum)%p,0,1};
}
void down(ll rt) {
tree[rt<<1].sum = (tree[rt<<1].sum*tree[rt].mul_tag+(tree[rt<<1].R-tree[rt<<1].L+1)*tree[rt].add_tag)%p;
tree[rt<<1|1].sum=(tree[rt<<1|1].sum*tree[rt].mul_tag+(tree[rt<<1|1].R-tree[rt<<1|1].L+1)*tree[rt].add_tag)%p;
tree[rt<<1].mul_tag=(tree[rt<<1].mul_tag*tree[rt].mul_tag)%p;
tree[rt<<1|1].mul_tag=(tree[rt<<1|1].mul_tag*tree[rt].mul_tag)%p;
tree[rt<<1].add_tag=(tree[rt<<1].add_tag*tree[rt].mul_tag+tree[rt].add_tag)%p;
tree[rt<<1|1].add_tag=(tree[rt<<1|1].add_tag*tree[rt].mul_tag+tree[rt].add_tag)%p;
tree[rt].add_tag=0;
tree[rt].mul_tag=1;
return;
}
void update(ll rt,ll x,ll y,ll k,ll op) {
if(tree[rt].L>y || tree[rt].R<x) return;
if(tree[rt].L>=x&&tree[rt].R<=y) {
if(op==1) {
tree[rt].sum = (tree[rt].sum * k) % p;
tree[rt].mul_tag = (tree[rt].mul_tag * k) % p;
tree[rt].add_tag = (tree[rt].add_tag * k) % p;
} else {
tree[rt].sum = (tree[rt].sum+(tree[rt].R-tree[rt].L+1) * k) % p;
tree[rt].add_tag = (tree[rt].add_tag + k) % p;
}
return;
}
if(tree[rt].add_tag||tree[rt].mul_tag!=1) down(rt);
update(rt<<1,x,y,k,op);
update(rt<<1|1,x,y,k,op);
tree[rt].sum = tree[rt<<1].sum + tree[rt<<1|1].sum;
}
ll get_sum(ll rt,ll x,ll y) {
if(tree[rt].R<x || tree[rt].L>y) return 0;
if(tree[rt].L>=x && tree[rt].R<=y) return tree[rt].sum%p;
if(tree[rt].add_tag||tree[rt].mul_tag!=1) down(rt);
return (get_sum(rt<<1,x,y) + get_sum(rt<<1|1,x,y)) % p;
}
int main() {
scanf("%lld%lld%lld",&n,&m,&p);
for(int i=1; i<=n; i++) scanf("%lld",&a[i]);
build(1,1,n);
while(m--) {
ll op,x,y,k;
scanf("%lld%lld%lld",&op,&x,&y);
if(op==1 || op==2) {
scanf("%lld",&k);
update(1,x,y,k,op);
} else {
cout<<get_sum(1,x,y)<<endl;
}
}
return 0;
}
/*
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
*/