三种操作:
1.区间加
2.区间乘
3.求区间和
用两个懒标记记录加(add)和乘(mul),注意mul初始为1。
当乘上一个数时,要将他的add标记也乘,这样下传标记时直接加上就可以了。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 10;
int n, q, m, a[N];
struct T {
int l, r, sum, mul, add;
#define l(p) t[p].l
#define r(p) t[p].r
#define sum(p) t[p].sum
#define mul(p) t[p].mul
#define add(p) t[p].add
}t[N << 2];
void pushup(int p) {
sum(p) = (sum(p << 1) + sum(p << 1 | 1)) % m;
}
void build(int p, int l, int r) {
l(p) = l, r(p) = r, mul(p) = 1;//***注意mul标记初始为1
if (l == r) {
sum(p) = a[l] % m;
return ;
}
int mid = (l + r) >> 1;
build(p << 1, l, mid);
build(p << 1 | 1, mid + 1, r);
pushup(p);
}
void pushdown(int p) {//下传标记
sum(p << 1) = (sum(p << 1) * mul(p) % m + ((r(p << 1) - l(p << 1) + 1) * add(p)) % m) % m;
sum(p << 1 | 1) = (sum(p << 1 | 1) * mul(p) % m + ((r(p << 1 | 1) - l(p << 1 | 1) + 1) * add(p)) % m) % m;
mul(p << 1) = (mul(p << 1) * mul(p)) % m;
mul(p << 1 | 1) = (mul(p << 1 | 1) * mul(p)) % m;
add(p << 1) = (add(p) + add(p << 1) * mul(p)) % m;
add(p << 1 | 1) = (add(p) + add(p << 1 | 1) * mul(p)) % m;
mul(p) = 1, add(p) = 0;//***清除标记
}
void modify1(int p, int l, int r, int val) {//乘
if (l(p) >= l && r(p) <= r) {
sum(p) = (sum(p) * val) % m;
add(p) = (add(p) * val) % m;
mul(p) = (mul(p) * val) % m;
return ;
}
pushdown(p);
int mid = (l(p) + r(p)) >> 1;
if (l <= mid) modify1(p << 1, l, r, val);
if (r > mid) modify1(p << 1 | 1, l, r, val);
pushup(p);
}
void modify2(int p, int l, int r, int val) {
if (l(p) >= l && r(p) <= r) {
sum(p) = (sum(p) + (r(p) - l(p) + 1) * val) % m;
add(p) = (add(p) + val) % m;
return ;
}
pushdown(p);
int mid = (l(p) + r(p)) >> 1;
if (l <= mid) modify2(p << 1, l, r, val);
if (r > mid) modify2(p << 1 | 1, l, r, val);
pushup(p);
}
int query(int p, int l, int r) {
if (l(p) >= l && r(p) <= r) return sum(p);
pushdown(p);
int res = 0;
int mid = (l(p) + r(p)) >> 1;
if (l <= mid) res = (res + query(p << 1, l, r)) % m;
if (r > mid) res = (res + query(p << 1 | 1, l, r)) % m;
return res;
}
signed main() {
cin >> n >> q >> m;
for (int i = 1; i <= n; i ++) cin >> a[i];
build(1, 1, n);
while (q --) {
int op, x, y, k;
cin >> op >> x >> y;
if (op == 1) {
cin >> k;
modify1(1, x, y, k);
}
else if (op == 2) {
cin >> k;
modify2(1, x, y, k);
}
else cout << query(1, x, y) << endl;
}
return 0;
}