【模板】线段树区间加、乘

只需要使用两个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 }

猜你喜欢

转载自www.cnblogs.com/devilk-sjj/p/9054556.html