1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
| // 더 많은 정보는 42jerrykim.github.io 에서 확인하세요.
#include <bits/stdc++.h>
using namespace std;
static const long long MOD = 1000000007LL;
struct Node {
long long sum;
long long add;
long long mul;
long long setVal;
bool hasSet;
Node(): sum(0), add(0), mul(1), setVal(0), hasSet(false) {}
};
struct SegTree {
int n;
vector<Node> t;
SegTree(int n): n(n), t(4 * n + 4) {}
static inline long long norm(long long x) {
x %= MOD;
if (x < 0) x += MOD;
return x;
}
void build(int idx, int l, int r, const vector<long long>& a) {
t[idx].add = 0; t[idx].mul = 1; t[idx].hasSet = false; t[idx].setVal = 0;
if (l == r) {
t[idx].sum = norm(a[l]);
return;
}
int m = (l + r) >> 1;
build(idx << 1, l, m, a);
build(idx << 1 | 1, m + 1, r, a);
t[idx].sum = (t[idx << 1].sum + t[idx << 1 | 1].sum) % MOD;
}
inline void applySet(int idx, int l, int r, long long val) {
val = norm(val);
t[idx].sum = (val * (r - l + 1)) % MOD;
t[idx].hasSet = true;
t[idx].setVal = val;
t[idx].mul = 1;
t[idx].add = 0;
}
inline void applyMul(int idx, int l, int r, long long val) {
val = norm(val);
t[idx].sum = (t[idx].sum * val) % MOD;
if (t[idx].hasSet) {
t[idx].setVal = (t[idx].setVal * val) % MOD;
} else {
t[idx].mul = (t[idx].mul * val) % MOD;
t[idx].add = (t[idx].add * val) % MOD;
}
}
inline void applyAdd(int idx, int l, int r, long long val) {
val = norm(val);
t[idx].sum = (t[idx].sum + val * (r - l + 1)) % MOD;
if (t[idx].hasSet) {
t[idx].setVal = (t[idx].setVal + val) % MOD;
} else {
t[idx].add = (t[idx].add + val) % MOD;
}
}
inline void push(int idx, int l, int r) {
if (l == r) return;
int m = (l + r) >> 1;
int lc = idx << 1, rc = idx << 1 | 1;
if (t[idx].hasSet) {
applySet(lc, l, m, t[idx].setVal);
applySet(rc, m + 1, r, t[idx].setVal);
t[idx].hasSet = false;
}
if (t[idx].mul != 1) {
applyMul(lc, l, m, t[idx].mul);
applyMul(rc, m + 1, r, t[idx].mul);
t[idx].mul = 1;
}
if (t[idx].add != 0) {
applyAdd(lc, l, m, t[idx].add);
applyAdd(rc, m + 1, r, t[idx].add);
t[idx].add = 0;
}
}
void rangeAdd(int idx, int l, int r, int ql, int qr, long long v) {
if (qr < l || r < ql) return;
if (ql <= l && r <= qr) { applyAdd(idx, l, r, v); return; }
push(idx, l, r);
int m = (l + r) >> 1;
rangeAdd(idx << 1, l, m, ql, qr, v);
rangeAdd(idx << 1 | 1, m + 1, r, ql, qr, v);
t[idx].sum = (t[idx << 1].sum + t[idx << 1 | 1].sum) % MOD;
}
void rangeMul(int idx, int l, int r, int ql, int qr, long long v) {
if (qr < l || r < ql) return;
if (ql <= l && r <= qr) { applyMul(idx, l, r, v); return; }
push(idx, l, r);
int m = (l + r) >> 1;
rangeMul(idx << 1, l, m, ql, qr, v);
rangeMul(idx << 1 | 1, m + 1, r, ql, qr, v);
t[idx].sum = (t[idx << 1].sum + t[idx << 1 | 1].sum) % MOD;
}
void rangeAssign(int idx, int l, int r, int ql, int qr, long long v) {
if (qr < l || r < ql) return;
if (ql <= l && r <= qr) { applySet(idx, l, r, v); return; }
push(idx, l, r);
int m = (l + r) >> 1;
rangeAssign(idx << 1, l, m, ql, qr, v);
rangeAssign(idx << 1 | 1, m + 1, r, ql, qr, v);
t[idx].sum = (t[idx << 1].sum + t[idx << 1 | 1].sum) % MOD;
}
long long rangeSum(int idx, int l, int r, int ql, int qr) {
if (qr < l || r < ql) return 0LL;
if (ql <= l && r <= qr) return t[idx].sum;
push(idx, l, r);
int m = (l + r) >> 1;
long long left = rangeSum(idx << 1, l, m, ql, qr);
long long right = rangeSum(idx << 1 | 1, m + 1, r, ql, qr);
return (left + right) % MOD;
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N, Q;
if (!(cin >> N >> Q)) return 0;
vector<long long> a(N + 1);
for (int i = 1; i <= N; ++i) {
long long x; cin >> x; a[i] = x % MOD;
}
SegTree st(N);
st.build(1, 1, N, a);
while (Q--) {
int op; cin >> op;
if (op == 1) { // add
int l, r; long long v; cin >> l >> r >> v;
st.rangeAdd(1, 1, N, l, r, v);
} else if (op == 2) { // multiply
int l, r; long long v; cin >> l >> r >> v;
st.rangeMul(1, 1, N, l, r, v);
} else if (op == 3) { // assign
int l, r; long long v; cin >> l >> r >> v;
st.rangeAssign(1, 1, N, l, r, v);
} else if (op == 4) { // sum
int l, r; cin >> l >> r;
cout << st.rangeSum(1, 1, N, l, r) % MOD << '\n';
}
}
return 0;
}
|