tags
根号分治
中文题面
给你一个由 500000 500000 500000 个整数(编号从 1 1 1 到 500000 500000 500000 )组成的数组 a a a 。最初 a a a 中的所有元素都为零。
您必须对这个数组进行两种类型的查询:
- 1 1 1 x x x y y y - a x a_x ax 增加 y y y ;
- 2 2 2 x x x y y y - 计算 ∑ i ∈ R ( x , y ) a i \sum\limits_{i \in R(x, y)} a_i i∈R(x,y)∑ai ,其中 R ( x , y ) R(x, y) R(x,y) 是所有从 1 1 1 到 500000 500000 500000 有余数 y y y modulo x x x 的整数的集合。
你能处理所有的查询吗?
输入
第一行包含一个整数 q q q ( 1 ≤ q ≤ 500000 1 \le q \le 500000 1≤q≤500000 ) - 查询次数。
然后是 q q q 行,每行描述一个查询。第 i i i 行包含三个整数 t i t_i ti 、 x i x_i xi 和 y i y_i yi ( 1 ≤ t i ≤ 2 1 \le t_i \le 2 1≤ti≤2 )。如果是 t i = 1 t_i = 1 ti=1 ,则是第一类查询、 1 ≤ x i ≤ 500000 1 \le x_i \le 500000 1≤xi≤500000 和 − 1000 ≤ y i ≤ 1000 -1000 \le y_i \le 1000 −1000≤yi≤1000 。如果是 t i = 2 t_i = 2 ti=2 ,则是第二类查询、 1 ≤ x i ≤ 500000 1 \le x_i \le 500000 1≤xi≤500000。
可以保证至少有一个查询属于 2 2 2 类型。
输出
为每个 2 2 2 类型的查询打印一个整数–答案。
思路
没有预处理,直接暴力,时间复杂度为O(q * n / x); 预处理时间复杂度O(nx),每次O(1)回答,O(x)修改,总时间复杂度O(nx),使用根号分治,当x <= 707时使用预处理方式解决,当x > 707时使用暴力算法解决,避免超时,本题得解
代码
#include <bits/stdc++.h>
using namespace std;
int s[708][708];
int v[500005];
// 707分界
inline void solve() {
const int n = 500000;
int m, x, y;
char op;
cin >> m;
while (m--) {
cin >> op >> x >> y;
if (op == '2') {
if (x <= 707) cout << s[x][y] << '\n';
else {
int res = 0;
for (register int i = 0; i * x + y <= n; i++) res += v[i * x + y];
cout << res << '\n';
}
}
else {
v[x] += y;
for (register int p = 1; p <= 707; p++) s[p][x % p] += y;
}
}
}
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
solve();
return 0;
}