それは、列の数にはよく知られている場合は、次の3つの操作を実行する必要があります。
1. Xを乗じた数のそれぞれのセクション
2. xの数のそれぞれのセクションプラス
3.セクションの数を決定し、各
この質問は二つの操作、満たすことで追加と乗算を、私たちのレイジー(レイジー)このような操作の動作を満たすことができます
注意すべき唯一の場所は、乗算は乗算の前に添加すると、その後、彼の父は、乗算ノードを伝えてから、ノードが非常に奇妙になります場合は、それが私たちの最終的な結果に影響を与える、さらに前に行わなければならないということです
次のようにコードがある(草、コピー&ペーストは私に4時間を破壊しました
//#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;
}