题目链接:https://www.acwing.com/problem/content/1279/
解题思路:直接开一个线段树,然后开懒惰标记,在pushdown的时候,先算乘法,再算除法。当乘法来的时候,将当前节点的add同时也乘上刚来的数字;其实,这类题都是这样,要去看一下法则的优先级。
贴上蒟蒻的代码一份:
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long LL;
const int maxn = 1e5 + 5;
int n, m, mod;
int a[maxn];
struct Treement {
int l, r;
LL sum;
LL add, mul;
}tr[maxn * 4];
inline void pushup(int u) {
tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
tr[u].sum %= mod;
}
inline void pushdown(int u) {
Treement &nodel = tr[u << 1], &noder = tr[u << 1 | 1];
nodel.add *= tr[u].mul; nodel.mul *= tr[u].mul; nodel.sum *= tr[u].mul;
noder.add *= tr[u].mul; noder.mul *= tr[u].mul; noder.sum *= tr[u].mul;
nodel.add += tr[u].add, nodel.sum += tr[u].add * (nodel.r - nodel.l + 1);
noder.add += tr[u].add, noder.sum += tr[u].add * (noder.r - noder.l + 1);
nodel.add %= mod; nodel.mul %= mod; nodel.sum %= mod;
noder.add %= mod; noder.mul %= mod; noder.sum %= mod;
tr[u].mul = 1, tr[u].add = 0;
}
inline void build(int u, int l, int r) {
tr[u] = {l, r, 0, 0, 1};
if(l == r) {
tr[u].sum = a[l];
return;
}
int mid = l + r >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
pushup(u);
}
inline void modify_mul(int u, int l, int r, LL x) {
if(l <= tr[u].l && tr[u].r <= r) {
tr[u].add *= x; tr[u].add %= mod;
tr[u].mul *= x; tr[u].mul %= mod;
tr[u].sum *= x; tr[u].sum %= mod;
return;
}
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
if(l <= mid) modify_mul(u << 1, l, r, x);
if(r > mid) modify_mul(u << 1 | 1, l, r, x);
pushup(u);
}
inline void modify_add(int u, int l, int r, LL x) {
if(l <= tr[u].l && tr[u].r <= r) {
tr[u].add += x; tr[u].add %= mod;
tr[u].sum += x * (tr[u].r - tr[u].l + 1);
tr[u].sum %= mod;
return;
}
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
if(l <= mid) modify_add(u << 1, l, r, x);
if(r > mid) modify_add(u << 1 | 1, l, r, x);
pushup(u);
}
inline LL query(int u, int l, int r) {
if(l <= tr[u].l && tr[u].r <= r) return tr[u].sum % mod;
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
LL res = 0;
if(l <= mid) res = query(u << 1, l, r);
if(r > mid) res += query(u << 1 | 1, l, r);
pushup(u);
return res % mod;
}
int main(void) {
// freopen("in.txt", "r", stdin);
scanf("%d%d", &n, &mod);
for(int i = 1; i <= n; i ++) {
scanf("%d", &a[i]);
a[i] %= mod;
}
build(1, 1, n);
scanf("%d", &m);
while(m --) {
int op, t, g;
LL c;
scanf("%d%d%d", &op, &t, &g);
if(op == 1) {
scanf("%lld", &c);
c %= mod;
modify_mul(1, t, g, c);
} else if(op == 2) {
scanf("%lld", &c);
c %= mod;
modify_add(1, t, g, c);
} else {
printf("%lld\n", query(1, t, g));
}
}
return 0;
}