线段树裸题不解释,注意取膜和乘法标记对加法标记的影响就好了
#include <bits/stdc++.h>
#define Ls(x) x << 1
#define Rs(x) x << 1 | 1
using namespace std;
int n, m;
long long mod;
const int maxn = 100000 + 10;
long long a[maxn];
template<class T>void read(T &x)
{
x = 0;int f = 0;int ch = getchar();
while(ch < '0' || ch > '9') {f |= (ch == '-'); ch = getchar();}
while(ch >= '0'&&ch <= '9'){x = x * 10+(ch^48); ch = getchar();}
x = f?-x:x;
return;
}
struct SegmentTree{
int l, r, len;
long long tag;
long long mult;
long long val;
SegmentTree()
{
tag = 0;val = 0;mult = 1;
l = r = len = 0;
}
}tre[maxn << 2];
void build(int rt, int l, int r)
{
tre[rt].l = l, tre[rt].r = r, tre[rt].len = r - l + 1;
if(l == r) {
tre[rt].val = a[l];
return ;
}
int mid = (l + r) >> 1;
build(Ls(rt), l, mid);
build(Rs(rt), mid + 1, r);
tre[rt].val = (tre[Ls(rt)].val + tre[Rs(rt)].val) % mod;
}
void push_down(int rt) {
tre[Ls(rt)].mult = tre[Ls(rt)].mult * tre[rt].mult % mod;
tre[Ls(rt)].tag = (tre[Ls(rt)].tag * tre[rt].mult + tre[rt].tag) % mod;
tre[Ls(rt)].val = (tre[Ls(rt)].val * tre[rt].mult + tre[rt].tag * (tre[Ls(rt)].len)) % mod;
tre[Rs(rt)].mult = tre[Rs(rt)].mult * tre[rt].mult % mod;
tre[Rs(rt)].tag = (tre[Rs(rt)].tag * tre[rt].mult + tre[rt].tag) % mod;
tre[Rs(rt)].val = (tre[Rs(rt)].val * tre[rt].mult + tre[rt].tag * (tre[Rs(rt)].len)) % mod;
tre[rt].mult=1;tre[rt].tag=0;
}
void update(int rt, int L, int R, long long delta, int k) {
int l = tre[rt].l, r = tre[rt].r;
int mid = (l + r) >> 1;
if(l >= L && r <= R) {
if(k == 2) {
tre[rt].tag = (tre[rt].tag + delta) % mod;
tre[rt].val = (tre[rt].val + delta * tre[rt].len) % mod;
}
else {
tre[rt].mult = tre[rt].mult * delta % mod;
tre[rt].tag = tre[rt].tag * delta % mod;
tre[rt].val = tre[rt].val * delta % mod;
}
return ;
}
if(tre[rt].mult != 1 || tre[rt].tag ) push_down(rt);
if(L <= mid) update(Ls(rt), L, R, delta, k);
if(R > mid) update(Rs(rt), L, R, delta, k);
tre[rt].val = (tre[Ls(rt)].val + tre[Rs(rt)].val) % mod;
return ;
}
long long query(int rt, int L, int R) {
int l = tre[rt].l, r = tre[rt].r;int mid = (l + r) >> 1;
if(l >= L && r <= R) {
return tre[rt].val;
}
if(tre[rt].mult != 1 || tre[rt].tag ) push_down(rt);
long long res = 0;
if(L <= mid) res += query(Ls(rt), L, R);
if(mid < R) res += query(Rs(rt), L, R);
return res % mod;
}
signed main()
{
read(n); read(mod);
for(int i = 1; i <= n; i++) read(a[i]);
read(m);
build(1, 1, n);
for(int i = 1, opt, l, r; i <= m; i++) {
read(opt); read(l); read(r);
long long dif;
if(opt == 3) {
printf("%lld\n", query(1, l, r));
}
else {
read(dif);
update(1, l ,r, dif, opt);
}
}
return 0;
}