分块思想
根号分治是一种将问题按数据规模分为“小数据”和“大数据”两类,分别采用互补的暴力策略,均摊时间复杂度使最坏时间复杂度降至可接受区间的算法优化思想。
学习根号分治思想也有助于分块这一数据结构的熟练使用。
CF1921F
这道题是根号分治的基础模板题,分别用预处理后缀和的后缀和与枚举两种暴力方法,若将断点设为 \(B\),则时间复杂度为 \(\frac{n^3}{B}+n^2B\),由基本不等式可知复杂度最优时 \(B=\sqrt{n}\)
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e5+500;
int T, n, q, s, d, k, a[N], s1[N][400], s2[N][400];
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> T;
while(T--){
for(int i = 1; i <= n; i++){
for(int j = 1; j <= 350; j++) s1[i][j] = s2[i][j] = 0;
}
cin >> n >> q;
int sq = sqrt(n);
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = n; i; i--){
for(int j = 1; j <= sq; j++) s1[i][j] = a[i] + s1[i+j][j];
}
for(int i = n; i; i--){
for(int j = 1; j <= sq; j++) s2[i][j] = s1[i][j] + s2[i+j][j];
}
while(q--){
cin >> s >> d >> k;
if(d <= sq) cout << s2[s][d]-s2[s+d*k][d]-k*s1[s+d*k][d] << " ";
else{
int res = 0;
for(int i = 1; i <= k; i++) res += a[s+d*(i-1)]*i;
cout << res << " ";
}
}
cout << '\n';
}
return 0;
}

浙公网安备 33010602011771号