1. 1. 题目
  2. 2. 题解
  3. 3.
  4. 4. 代码

题目

link

题解

线段树

考虑两个tag,mul与add

表示[l, mid] [mid + 1, r]这两个区间分别需要* mul + tag

下传标记的时候[l, mid] [mid + 1, r]这两个子区间的tag,mul tag直接*mul[u],add tag要* mul[u] + tag[u]

1.change最后返回前要pushup一下

2.下传的时候u要穿ls,rs(

3.不开longlong见祖宗

代码

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
#include<bits/stdc++.h>
const int N = 1e5 + 10;
int n;
using namespace std;
#define int long long
int a[N];
const int mod = 571373;

namespace Segmenttree
{
#define ls (u << 1)
#define rs ((u << 1) | 1)
int tree[N << 2];
int tagcheng[N << 2], tagjia[N << 2];
void init()
{
for(int i = 1;i < 4 * n;i++)
tagcheng[i] = 1, tagjia[i] = 0;
}
void pushup(int u)
{
tree[u] = (tree[ls] + tree[rs]) % mod;
}

void build(int u, int l, int r)
{
if(l == r)
{
tree[u] = a[l];
return;
}
int mid = (l + r) >> 1;
build(ls, l, mid);
build(rs, mid + 1, r);
pushup(u);
}

void pushdown(int u, int l, int r)
{
int mid = (l + r) >> 1;
//[l, mid]、[mid + 1, r]
tree[ls] = (tree[ls] * tagcheng[u] + tagjia[u] * (mid - l + 1)) % mod;
tree[rs] = (tree[rs] * tagcheng[u] + tagjia[u] * (r - mid)) % mod;
tagcheng[ls] = tagcheng[ls] * tagcheng[u] % mod;
tagcheng[rs] = tagcheng[rs] * tagcheng[u] % mod;
tagjia[ls] = (tagjia[ls] * tagcheng[u] + tagjia[u]) % mod;
tagjia[rs] = (tagjia[rs] * tagcheng[u] + tagjia[u]) % mod;
tagjia[u] = 0;
tagcheng[u] = 1;
}

void change(int u, int l, int r, int L, int R, int val, int type)
{
if(L <= l && r <= R)
{
// cout << l << " " << r << " was included"<<endl;
if(type == 0)
{
tree[u] = (tree[u] + val * (r - l + 1)) % mod;
tagjia[u] = (tagjia[u] + val) % mod;
}
else
{

tree[u] = tree[u] * val % mod;
tagcheng[u] = tagcheng[u] * val % mod;
tagjia[u] = tagjia[u] * val % mod;
// if(l == 4 && r == 4) cout << u<<" "<< val << " " << type << "qaqaqaq"<< " " << tree[u] << " "<< endl;
}
return;
}
// cout << l << " " << r << endl;
pushdown(u, l, r);
int mid = (l + r) >> 1;
if(L <= mid) change(ls, l, mid, L, R, val, type);
if(R > mid) change(rs, mid + 1, r, L, R, val, type);
pushup(u);
}

int query(int u, int l, int r, int L, int R)
{
if(L <= l && r <= R)
{
// cout << "query : " << l << " " << r << "sum: " << tree[u] << " " << u << endl;
return tree[u];
}
int ans = 0;
pushdown(u, l, r);
int mid = (l + r) >> 1;
if(L > r || R < l) return 0;
if(L <= mid) ans = (ans + query(ls, l, mid, L, R)) % mod;
if(R > mid) ans = (ans + query(rs, mid + 1, r, L, R)) % mod;
// cout << "query : " << l << " " << r << "sum: " << ans << " " << u << endl;
return ans;
}
}
signed main()
{
// ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int q, m;
cin >> n >> q >> m;
for(int i = 1;i <= n;i++)
cin >> a[i];
int opt;
Segmenttree::init();
Segmenttree::build(1, 1, n);
while(q--)
{
int x, y, k;
cin >> opt;
if(opt == 1)
{
cin >> x >> y >> k;
Segmenttree::change(1, 1, n, x, y, k, 1);
// cout << "qwq" << Segmenttree::query(1, 1, n, 4, 4) << '\n';
}
else if(opt == 2)
{
cin >> x >> y >> k;
Segmenttree::change(1, 1, n, x, y, k, 0);
// cout << "qwq" << " " << Segmenttree::query(1, 1, n, x, y) << '\n';
}
else
{
cin >> x >> y;
cout << Segmenttree::query(1, 1, n, x, y) << '\n';
}
}
return 0;
}