If that is known to a number of columns, you need to perform the following three operations:
1. The section of each of a number multiplied by x
2. The section of each of a number of x plus
3. determine a number of sections and each
This question is to meet two operations, addition and multiplication , is able to meet our Lazy (Lazy) the operation of such operations
The only place to note is that multiplication must be carried out before the addition, if the addition before multiplication, then the node from when his father passed down multiplication node will become very strange, it will affect our final result
Then the code is as follows (grass, copy and paste destroyed me four hours
//#define fre yes
#include <cstdio>
#define int long long
const int N = 100005;
struct Node {
int l, r, w;
int addv, mul;
} tree[N << 2];
int MOD;
void build(int k, int l, int r) {
tree[k].l = l; tree[k].r = r; tree[k].addv = 0; tree[k].mul = 1;
if(l == r) {
scanf("%lld", &tree[k].w);
tree[k].w %= MOD;
return ;
}
int mid = (l + r) >> 1;
build(k * 2, l, mid);
build(k * 2 + 1, mid + 1, r);
tree[k].w = (tree[k * 2].w + tree[k * 2 + 1].w) % MOD;
}
void pushdown(int k) {
tree[k * 2].mul = (tree[k * 2].mul * tree[k].mul) % MOD;
tree[k * 2 + 1].mul = (tree[k * 2 + 1].mul * tree[k].mul) % MOD;
tree[k * 2].addv = (tree[k * 2].addv * tree[k].mul + tree[k].addv) % MOD;
tree[k * 2 + 1].addv = (tree[k * 2 + 1].addv * tree[k].mul + tree[k].addv) % MOD;
tree[k * 2].w = (tree[k * 2].w * tree[k].mul + (tree[k * 2].r - tree[k * 2].l + 1) * tree[k].addv) % MOD;
tree[k * 2 + 1].w = (tree[k * 2 + 1].w * tree[k].mul + (tree[k * 2 + 1].r - tree[k * 2 + 1].l + 1) * tree[k].addv) % MOD;
tree[k].mul = 1;
tree[k].addv = 0;
}
void change_interval(int k, int l, int r, int x) {
if(tree[k].l >= l && tree[k].r <= r) {
tree[k].w = (tree[k].w + (tree[k].r - tree[k].l + 1) * x) % MOD;
tree[k].addv = (tree[k].addv + x) % MOD;
return ;
}
if(tree[k].addv || tree[k].mul != 1) pushdown(k);
int mid = (tree[k].l + tree[k].r) >> 1;
if(mid >= l) change_interval(k * 2, l, r, x);
if(mid < r) change_interval(k * 2 + 1, l, r, x);
tree[k].w = (tree[k * 2].w + tree[k * 2 + 1].w) % MOD;
}
void mul_interval(int k, int l, int r, int x) {
if(tree[k].l >= l && tree[k].r <= r) {
tree[k].w = (tree[k].w * x) % MOD;
tree[k].addv = (tree[k].addv * x) % MOD;
tree[k].mul = (tree[k].mul * x) % MOD;
return ;
}
if(tree[k].addv || tree[k].mul != 1) pushdown(k);
int mid = (tree[k].l + tree[k].r) >> 1;
if(mid >= l) mul_interval(k * 2, l, r, x);
if(mid < r) mul_interval(k * 2 + 1, l, r, x);
tree[k].w = (tree[k * 2].w + tree[k * 2 + 1].w) % MOD;
}
int ans;
void query(int k, int l, int r) {
if(tree[k].l >= l && tree[k].r <= r) {
ans = (ans + tree[k].w) % MOD;
return ;
}
if(tree[k].addv || tree[k].mul != 1) pushdown(k);
int mid = (tree[k].l + tree[k].r) >> 1;
if(mid >= l) query(k * 2, l, r);
if(mid < r) query(k * 2 + 1, l, r);
}
//void ask(int k) {
// if(tree[k].l == tree[k].r) {
// printf("%d ", tree[k].w);
// return ;
// }
//
// if(tree[k].addv || tree[k].mul != 1) pushdown(k);
// int mid = (tree[k].l + tree[k].r) >> 1;
// ask(k * 2);
// ask(k * 2 + 1);
//}
signed main() {
static int n, m;
scanf("%lld %lld %lld", &n, &m, &MOD);
build(1, 1, n);
for (int i = 1; i <= m; i++) {
int q, x, y, k;
scanf("%lld %lld %lld", &q, &x, &y);
if(q == 1) {
scanf("%lld", &k);
mul_interval(1, x, y, k);
}
if(q == 2) {
scanf("%lld", &k);
change_interval(1, x, y, k);
}
// ask(1);
// puts("");
if(q == 3) {
ans = 0;
query(1, x, y);
printf("%lld\n", ans % MOD);
}
} return 0;
}