题意:3e5个数,3e5组询问,每组询问给(a,b)—— 问从a,a+b,a+2b,。。。一直到下标超过n为止所有下标的和是多少
分析:还是很妙的很优雅的分块 —— 首先这个暴力肯定不行,想想怎么优化,发现如果存在相同的b,那么可以做一个后缀和优化,但是如果他全都不一样,这种极端情况也是可以卡成n2的,—— 但发现数据大的时候其实直接做即可,这里就要取一个优雅的平衡点 —— ,大于根号的直接暴力,小于的用前缀和处理,复杂度最大是
【离线版】
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 15;
const int mo = 998244353;
#define pb push_back
#define pii pair<int,int>
#define ft first
#define sd second
#define ffor(i,a,b,c) for(int i=(a);i<(b);i+=(c))
#define For(i,a,b,c) for(int i=(a);i<=(b);i+=(c))
#define rfor(i,a,b,c) for(int i=(a);i>(b);i-=(c))
#define Rfor(i,a,b,c) for(int i=(a);i>=(b);i-=(c))
#define all(x) (x).begin(), (x).end()
#define debug1(x) cerr<<"! "<<x<<endl;
#define debug2(x,y) cerr<<"# "<<x<<" "<<y<<endl;
class Partition
{
public:
Partition(int _n) : n(_n) {
v.resize(n + 1);
for (int i = 1; i <= n; i++) {
cin >> v[i];
}
blo = sqrt(n);
pr.resize(blo + 1);
}
void init() {
sort(q.begin(), q.end());
int lst = -1;
for (auto x : q) {
int i = x.ft.ft;
if (i > blo) {
ll res = 0;
for (int j = x.ft.sd; j <= n; j += i) {
res += v[j];
}
ans[x.sd] = res;
continue;
}
if (i == lst) {
ans[x.sd] = pr[x.ft.sd];
continue;
}
pr.clear();
pr.resize(n + 1);
for (int j = n; j >= 1; j--) {
if (j + i <= n) {
pr[j] += pr[j + i] + v[j];
} else {
pr[j] += v[j];
}
}
ans[x.sd] = pr[x.ft.sd];
lst = i;
}
}
void GetQ() {
int m; cin >> m; ans.resize(m + 1);
for (int i = 1; i <= m; i++) {
int a, b; cin >> a >> b;
q.pb({{b, a}, i});
}
init();
for (int i = 1; i <= m; i++) {
cout << ans[i] << '\n';
}
}
private:
vector<int> v; vector<pair<pii, int>> q;
vector<ll> pr, ans;
int n, blo;
};
void slv() {
int n; cin >> n;
Partition Pt(n);
Pt.GetQ();
}
int main() {
ios::sync_with_stdio(false); cin.tie(0);
slv();
}
【在线版】
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6+15;
const int mo = 998244353;
#define pb push_back
#define pii pair<int,int>
#define ft first
#define sd second
#define ffor(i,a,b,c) for(int i=(a);i<(b);i+=(c))
#define For(i,a,b,c) for(int i=(a);i<=(b);i+=(c))
#define rfor(i,a,b,c) for(int i=(a);i>(b);i-=(c))
#define Rfor(i,a,b,c) for(int i=(a);i>=(b);i-=(c))
#define all(x) (x).begin(), (x).end()
#define debug1(x) cerr<<"! "<<x<<endl;
#define debug2(x,y) cerr<<"# "<<x<<" "<<y<<endl;
class Partition
{
public:
Partition(int _n) : n(_n) {
v.resize(n + 1);
for(int i = 1; i <= n; i++) {
cin >> v[i];
}
blo = sqrt(n);
pr.resize(blo + 1);
for(int i = 1; i <= blo ;i ++) {
pr[i].resize(n + 1);
for(int j = n; j >= 1; j--) {
if(j + i <= n) {
pr[i][j] += pr[i][j + i] + v[j];
} else {
pr[i][j] += v[j];
}
}
}
}
ll query(int a, int b) {
if(b > blo) {
ll ans = 0;
for(int i = a; i <= n; i+=b) {
ans += v[i];
}
return ans;
} else {
return pr[b][a];
}
}
private:
vector<int> v;
vector<vector<ll>> pr;
int n, blo;
};
void slv(){
int n; cin >> n;
Partition Pt(n);
int m; cin >> m;
for(int i = 1; i <= m; i++) {
int a, b; cin >> a >> b;
cout << Pt.query(a, b) << '\n';
}
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);
slv();
}
PS:自从换成C++的写法突然感觉之前函数的写法有点丑hh