-分块-数论- [CF920F]SUM and REPLACE

题目描述

给你一个数组$a_i$​,$D(x)$为$x$的约数个数

两种操作:

1.将$[l,r]$的$a_i$替换为$D(a_i)$

2.输出$\sum^r_{i=l}a_i$

输入样例

7 6
6 4 1 10 3 2 4
2 1 7
2 4 5
1 3 5
2 4 4
1 5 7
2 1 7

输出样例

30
13
4
22

Solution

这道题和上帝造题七分钟2有点相似,只不过是把区间开放方成了区间改约数个数。

标记是块内是否每个数都小于等于2。

Code

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
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define MAXN 3010002
#define MX 1000100
#define ll long long
using namespace std;
int b[MAXN], n, sq, m;
ll s[MAXN], a[MAXN];
bool v[MAXN];
bool chk[MX];
int p[MX], d[MX], tot, num[MX];
inline int max(int a, int b) {
if (a > b) return a;
else return b;
}
inline int min(int a, int b) {
if (a < b) return a;
else return b;
}
void getd() {
chk[1] = 0;
d[1] = 1;
for (int i = 2; i <= MX; i++) {
if (!chk[i]) {
p[++tot] = i;
d[i] = 2;
num[i] = 1;
}
for (int j = 1; j <= tot && i * p[j] <= MX; j++) {
chk[i * p[j]] = 1;
if (!(i % p[j])) {
num[i * p[j]] = num[i] + 1;
d[i * p[j]] = d[i] / (num[i] + 1) * (num[i * p[j]] + 1);
break;
}
else {
d[i * p[j]] = d[i] * d[p[j]];
num[i * p[j]] = 1;
}
}
}
}
inline void quarysqrt(int x) {
if (v[x]) return;
v[x] = 1;
a[x] = 0;
for (int i = (x - 1) * sq + 1; i <= x * sq; i++) {
s[i] = d[s[i]];
a[x] += s[i];
if (s[i] > 2) v[x] = 0;
}
}
inline void add(int x, int y) {
if (v[b[x]] == 0) {
for (int i = x; i <= min(b[x] * sq, y); i++) {
a[b[x]] -= s[i];
s[i] = d[s[i]];
a[b[x]] += s[i];
}
v[b[x]] = 1;
for (int i = (b[x] - 1) * sq + 1; i <= b[x] * sq; i++) {
if (s[i] > 2) {
v[b[x]] = 0;
break;
}
}
}
if (b[x] != b[y] && v[b[y]] == 0) {
for (int i = (b[y] - 1) * sq + 1; i <= y; i++) {
a[b[y]] -= s[i];
s[i] = d[s[i]];
a[b[y]] += s[i];
}
v[b[y]] = 1;
for (int i = (b[y] - 1) * sq + 1; i <= b[y] * sq; i++) {
if (s[i] > 2) {
v[b[y]] = 0;
break;
}
}
}
for (int i = b[x] + 1; i <= b[y] - 1; i++) {
quarysqrt(i);
}
}
ll getsum(int x , int y) {
ll ans = 0;
for (int i = x; i <= min(b[x] * sq , y); i++) {
ans += s[i];
}
if (b[x] != b[y]) {
for (int i = (b[y] - 1) * sq + 1; i <= y; i++) {
ans += s[i];
}
}
for (int i = b[x] + 1; i < b[y]; i++) {
ans += a[i];
}
return ans;
}
int main() {
memset(v, 0, sizeof (v));
scanf("%d%d", &n, &m);
getd();
sq = sqrt(n);
for (int i = 1; i <= n; i++) {
scanf("%lld", &s[i]);
}
for (int i = 1; i <= n; i++) {
b[i] = (i - 1) / sq + 1;
a[b[i]] += s[i];
}
for (int i = 1; i <= m; i++) {
int x, y, c;
scanf("%d%d%d", &c, &x, &y);
if (x > y) {
swap(x, y);
}
if (c == 1) {
add(x, y);
}
else printf("%lld\n", getsum(x, y));
}
return 0;
}
文章作者: RiverFun
文章链接: https://stevebraveman.github.io/blog/2019/03/05/66/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 RiverFun

评论