只需要使用两个lazy-tag(addv, mulv)来维护,一个维护区间加,一个维护区间乘。
注意mulv标记应在建树的时候初始化成1.
在下传标记的时候,mulv下传时会对addv造成影响,所以修改addv时要考虑到mulv
一定要开long long,也要检查Update, down这些函数里需要开long long的有没有开
【代码:】
1 //线段树维护区间加、乘 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 using namespace std; 6 7 const int MAXN = 500000 + 1; 8 const int ADD = 1, MUL = 2; 9 10 int n, m, p; 11 long long a[MAXN]; 12 struct Segment { 13 long long sum, addv, mulv; 14 }t[MAXN << 2]; 15 16 inline long long read() { 17 long long x = 0, f = 1; char ch = getchar(); 18 while(ch < '0' || ch > '9') { 19 if(ch == '-') f = -1; 20 ch = getchar(); 21 } 22 while(ch >= '0' && ch <= '9') 23 x = (x << 3) + (x << 1) + ch - 48, ch = getchar(); 24 return x * f; 25 } 26 27 void Build(int o, int l, int r) { 28 t[o].mulv = 1; 29 if(l == r) t[o].sum = a[l]; 30 else { 31 int mid = (l + r) >> 1; 32 Build(o << 1, l, mid); 33 Build(o << 1|1, mid + 1, r); 34 t[o].sum = (t[o << 1].sum + t[o << 1|1].sum) % p; 35 } 36 } 37 38 inline void down(int o, int len) { 39 long long mul = t[o].mulv, add = t[o].addv; 40 t[o << 1].sum = (t[o << 1].sum * mul + add * (len - (len >> 1))) % p; 41 t[o << 1|1].sum = (t[o << 1|1].sum * mul + add * (len >> 1)) % p; 42 t[o << 1].mulv = (t[o << 1].mulv * mul) % p; 43 t[o << 1|1].mulv = (t[o << 1|1].mulv * mul) % p; 44 t[o << 1].addv = (t[o << 1].addv * mul + add) % p; 45 t[o << 1|1].addv = (t[o << 1|1].addv * mul + add) % p; 46 t[o].mulv = 1, t[o].addv = 0; 47 } 48 void Update(int o, int l, int r, int ul, int ur, long long v, int fl) { 49 if(ul <= l && r <= ur) { 50 if(fl == 1) { 51 t[o].sum = (t[o].sum + v * (r - l + 1)) % p; 52 t[o].addv = (t[o].addv + v) % p; 53 } 54 else if(fl == 2) { 55 t[o].sum = (t[o].sum * v) % p; 56 t[o].mulv = (t[o].mulv * v) % p; 57 t[o].addv = (t[o].addv * v) % p; 58 } 59 } 60 else { 61 if(t[o].mulv != 1 || t[o].addv) 62 down(o, r - l + 1); 63 int mid = (l + r) >> 1; 64 if(ul <= mid) Update(o << 1, l, mid, ul, ur, v, fl); 65 if(ur > mid) Update(o << 1|1, mid + 1, r, ul, ur, v, fl); 66 t[o].sum = (t[o << 1].sum + t[o << 1|1].sum) % p; 67 } 68 } 69 70 long long Query(int o, int l, int r, int ql, int qr) { 71 if(ql <= l && r <= qr) return t[o].sum % p; 72 int mid = (l + r) >> 1; 73 long long ret = 0; 74 if(t[o].mulv != 1 || t[o].addv) 75 down(o, r - l + 1); 76 if(ql <= mid) ret += Query(o << 1, l, mid, ql, qr); 77 if(qr > mid) ret += Query(o << 1|1, mid + 1, r, ql, qr); 78 return ret % p; 79 } 80 81 int main() { 82 n = read(), m = read(), p = read(); 83 for(int i=1; i<=n; ++i) 84 a[i] = read(); 85 Build(1, 1, n); 86 while(m--) { 87 long long fl = read(), x = read(), y = read(); 88 if(fl == 1) { 89 long long k = read(); 90 Update(1, 1, n, x, y, k, MUL); 91 } 92 else if(fl == 2) { 93 long long k = read(); 94 Update(1, 1, n, x, y, k, ADD); 95 } 96 else printf("%lld\n", Query(1, 1, n, x, y)); 97 } 98 }