洛谷 P3373 【模板】线段树 2
传送门
根据一大堆不知名的神奇原理,我们先放乘法标记,再放加法标记(其实是我不知道咋说......)
如果非要了解为什么先乘再加的话,click here-->
主要就是区间乘,区间加以及区间求和,下面就放代码吧
#include <bits/stdc++.h>
#define int long long
#define N 400011
#define lson rt << 1
#define rson rt << 1 | 1
using namespace std;
inline int read() {
char c = getchar();
int x = 0, f = 1;
for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
return x * f;
}
int n, m, mod, wl, wr, wv, ans;
struct node {
int l, r, w, fc, fj;
} a[N];
void pushup(int rt) {
a[rt].w = (a[lson].w + a[rson].w) % mod;
}
void build(int rt, int l, int r) {
a[rt].l = l;
a[rt].r = r;
a[rt].fj = 0;
a[rt].fc = 1;
if(a[rt].l == a[rt].r) {
a[rt].w = read();
return;
}
int m = (l + r) >> 1;
build(lson, l, m);
build(rson, m + 1, r);
pushup(rt);
}
void pushdown(int rt, int l, int r, int m) {
a[lson].w *= a[rt].fc;
a[rson].w *= a[rt].fc;
a[lson].w += a[rt].fj * (m - l + 1);
a[rson].w += a[rt].fj * (r - m);
a[lson].fc *= a[rt].fc;
a[rson].fc *= a[rt].fc;
a[lson].fj *= a[rt].fc;
a[rson].fj *= a[rt].fc;
a[lson].fj += a[rt].fj;
a[rson].fj += a[rt].fj;
a[rt].fc = 1;
a[rt].fj = 0;
a[lson].w %= mod;
a[lson].fc %= mod;
a[lson].fj %= mod;
a[rson].w %= mod;
a[rson].fc %= mod;
a[rson].fj %= mod;
}
void add(int rt, int l, int r,int v) {
if(a[rt].l > r || a[rt].r < l) return;
if(l <= a[rt].l && a[rt].r <= r) {
a[rt].w = (a[rt].w + v * (a[rt].r - a[rt].l + 1)) % mod;
a[rt].fj = (a[rt].fj + v) % mod;
return;
}
int m = (a[rt].l + a[rt].r) >> 1;
pushdown(rt, a[rt].l, a[rt].r, m);
add(lson, l, r, v);
add(rson, l, r, v);
pushup(rt);
}
void mul(int rt, int l, int r, int v) {
if(a[rt].l > r || a[rt].r < l) return;
if(l <= a[rt].l && a[rt].r <= r) {
a[rt].w *= v % mod;
a[rt].fc *= v % mod;
a[rt].fj *= v % mod;
return;
}
int m = (a[rt].l + a[rt].r) >> 1;
pushdown(rt, a[rt].l, a[rt].r, m);
mul(lson, l, r, v);
mul(rson, l, r, v);
pushup(rt);
}
void sum(int rt, int l, int r) {
if(a[rt].l > r || a[rt].r < l) return;
if(l <= a[rt].l && a[rt].r <= r) {
ans = (ans + a[rt].w) % mod;
return;
}
int m = (a[rt].l + a[rt].r) >> 1;
pushdown(rt, a[rt].l, a[rt].r, m);
sum(lson, l, r);
sum(rson, l, r);
}
signed main() {
n = read(), m = read(), mod = read();
build(1, 1, n);
for(int i = 1; i <= m; i ++) {
int p = read();
if(p ==1) {
wl = read(), wr = read(), wv = read();
mul(1, wl, wr, wv);
} else if(p == 2) {
wl = read(), wr = read(), wv = read();
add(1, wl, wr, wv);
} else if(p ==3) {
wl = read(), wr = read();
sum(1, wl, wr);
cout << ans % mod <<'\n';
ans = 0;
}
}
return 0;
}