当日总结
二小姐有一个长为
𝑛
n 的数组
𝑎
a,她会命令小红执行如下两种指令:
∙
∙
1
𝑥
𝑦
1 x y:将数组的第
𝑥
x 位修改为
𝑦
y。
∙
∙
2
𝑙
𝑟
2 l r:查询在区间
[
𝑙
,
𝑟
]
[l,r] 内任取两个元素,其乘积是
495
495 倍数的方案数。
请你帮帮小红。
输入描述:
第一行输入两个整数
𝑛
,
𝑞
(
1
≦
𝑛
,
𝑞
≦
2
×
1
0
5
)
n,q(1≦n,q≦2×10
5
)。
第二行输入
𝑛
n 个整数
𝑎
𝑖
(
1
≦
𝑎
𝑖
≦
1
0
9
)
a
i
(1≦a
i
≦10
9
)。
之后的
𝑞
q 行,每行输入一条指令
1
𝑥
𝑦
(
1
≦
𝑥
≦
𝑛
,
1
≦
𝑦
≦
1
0
9
)
1 x y(1≦x≦n,1≦y≦10
9
) 或
2
𝑙
𝑟
(
1
≦
𝑙
<
𝑟
≦
𝑛
)
2 l r(1≦l<r≦n)。
特殊的,保证至少会有一次查询指令。
include <bits/stdc++.h>
using namespace std;
define ll long long
const int N = 200010;
const int STATES = 12; // 3 (for 3^0,1,2) * 2 (5^0,1) * 2 (11^0,1)
struct Node {
ll cnt[STATES] = {0};
};
Node sg[N << 2];
ll a[N];
// 将 (c3, c5, c11) 编码为 0~11
int encode(int c3, int c5, int c11) {
return c3 * 4 + c5 * 2 + c11;
}
// 获取 x 对应的状态
int getState(ll x) {
int c3 = 0, c5 = 0, c11 = 0;
while (x % 3 == 0) { c3++; x /= 3; }
while (x % 5 == 0) { c5++; x /= 5; }
while (x % 11 == 0) { c11++; x /= 11; }
c3 = min(c3, 2);
c5 = min(c5, 1);
c11 = min(c11, 1);
return encode(c3, c5, c11);
}
void setNode(Node &nd, ll val) {
memset(nd.cnt, 0, sizeof(nd.cnt));
int s = getState(val);
nd.cnt[s] = 1;
}
void pushup(int u) {
for (int i = 0; i < STATES; i++) {
sg[u].cnt[i] = sg[u << 1].cnt[i] + sg[u << 1 | 1].cnt[i];
}
}
void build(int u, int l, int r) {
if (l == r) {
setNode(sg[u], a[l]);
return;
}
int mid = (l + r) >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
pushup(u);
}
void update(int pos, int l, int r, int u, ll x) {
if (l == r) {
a[pos] = x;
setNode(sg[u], x);
return;
}
int mid = (l + r) >> 1;
if (pos <= mid) {
update(pos, l, mid, u << 1, x);
} else {
update(pos, mid + 1, r, u << 1 | 1, x);
}
pushup(u);
}
Node query(int ql, int qr, int l, int r, int u) {
if (ql <= l && r <= qr) {
return sg[u];
}
int mid = (l + r) >> 1;
Node res;
bool leftDone = false, rightDone = false;
if (ql <= mid) {
res = query(ql, qr, l, mid, u << 1);
leftDone = true;
}
if (qr > mid) {
Node right = query(ql, qr, mid + 1, r, u << 1 | 1);
if (leftDone) {
for (int i = 0; i < STATES; i++) {
res.cnt[i] += right.cnt[i];
}
} else {
res = right;
}
}
return res;
}
ll calcAns(ll cnt[STATES]) {
ll ans = 0;
for (int i = 0; i < STATES; i++) {
int a = i / 4; // c3
int b = (i >> 1) & 1; // c5
int c = i & 1; // c11
for (int j = i; j < STATES; j++) {
int d = j / 4;
int e = (j >> 1) & 1;
int f = j & 1;
if (a + d >= 2 && b + e >= 1 && c + f >= 1) {
if (i == j) {
ans += cnt[i] * (cnt[i] - 1) / 2;
} else {
ans += cnt[i] * cnt[j];
}
}
}
}
return ans;
}
void solve() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, q;
cin >> n >> q;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
build(1, 1, n);
while (q--) {
int op, x;
ll y;
cin >> op >> x >> y;
if (op == 1) {
update(x, 1, n, 1, y);
} else {
Node res = query(x, y, 1, n, 1);
cout << calcAns(res.cnt) << '\n';
}
}
}
int main() {
solve();
return 0;
}

浙公网安备 33010602011771号