Luogu U140092 线段树练习

题目描述

https://www.luogu.com.cn/problem/U140092

博客中的例题

Solution

普通关系标记的使用

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
#include <iostream>
#include <cstdio>
#include <cctype>
#define maxn 100010
#define ll long long
#define cS const Seg
#define gc getchar
using namespace std;

int read() {
int x = 0; char c = gc();
while (!isdigit(c)) c = gc();
while (isdigit(c)) x = x * 10 + c - '0', c = gc();
return x;
}

const int p = 1000000007;

int n, m, a[maxn], b[maxn];

#define lc i << 1
#define rc i << 1 | 1
struct Seg {
ll v, a, b, adda, addb;
} T[maxn * 4];
inline void maintain(int i) {
T[i].v = (T[lc].v + T[rc].v) % p;
T[i].a = (T[lc].a + T[rc].a) % p;
T[i].b = (T[lc].b + T[rc].b) % p;
}

void build(int i, int l, int r) {
if (l == r) {
T[i].v = 1ll * a[l] * b[l] % p;
T[i].a = a[l]; T[i].b = b[l]; return ;
} int m = l + r >> 1;
build(lc, l, m); build(rc, m + 1, r);
maintain(i);
}

inline void Update_v(int i, int l, int r, ll adda, ll addb) {
T[i].v = (T[i].v + T[i].a * addb + T[i].b * adda + adda * addb % p * (r - l + 1)) % p;
T[i].a = (T[i].a + adda * (r - l + 1)) % p;
T[i].b = (T[i].b + addb * (r - l + 1)) % p;
}

inline void Update_tag(int i, int l, int r, ll adda, ll addb) {
T[i].adda = (T[i].adda + adda) % p;
T[i].addb = (T[i].addb + addb) % p;
}

inline void pushdown(int i, int l, int r) {
ll &adda = T[i].adda, &addb = T[i].addb; int m = l + r >> 1;

Update_v(lc, l, m, adda, addb); Update_v(rc, m + 1, r, adda, addb);

Update_tag(lc, l, m, adda, addb); Update_tag(rc, m + 1, r, adda, addb);

adda = addb = 0;
}

void update_adda(int i, int l, int r, int L, int R, int v) {
if (l > R || r < L) return ;
if (L <= l && r <= R) return Update_v(i, l, r, v, 0), Update_tag(i, l, r, v, 0);
int m = l + r >> 1; pushdown(i, l, r);
update_adda(lc, l, m, L, R, v); update_adda(rc, m + 1, r, L, R, v);
maintain(i);
}

void update_addb(int i, int l, int r, int L, int R, int v) {
if (l > R || r < L) return ;
if (L <= l && r <= R) return Update_v(i, l, r, 0, v), Update_tag(i, l, r, 0, v);
int m = l + r >> 1; pushdown(i, l, r);
update_addb(lc, l, m, L, R, v); update_addb(rc, m + 1, r, L, R, v);
maintain(i);
}

int query(int i, int l, int r, int L, int R) {
if (l > R || r < L) return 0;
if (L <= l && r <= R) return T[i].v;
int m = l + r >> 1; pushdown(i, l, r);
return (query(lc, l, m, L, R) + query(rc, m + 1, r, L, R)) % p;
}

inline void solve_1() {
int x = read(), y = read(), z = read();
update_adda(1, 1, n, x, y, z);
}

inline void solve_2() {
int x = read(), y = read(), z = read();
update_addb(1, 1, n, x, y, z);
}

inline void solve_3() {
int x = read(), y = read();
printf("%d\n", query(1, 1, n, x, y));
}

int main() {
n = read(); m = read();
for (int i = 1; i <= n; ++i) a[i] = read(), b[i] = read();
build(1, 1, n);
for (int i = 1; i <= m; ++i) {
int opt = read();
switch (opt) {
case 1 : solve_1(); break;
case 2 : solve_2(); break;
case 3 : solve_3(); break;
}
}
return 0;
}