分块思想

根号分治是一种将问题按数据规模分为“小数据”和“大数据”两类,分别采用互补的暴力策略,均摊时间复杂度使最坏时间复杂度降至可接受区间的算法优化思想。
学习根号分治思想也有助于分块这一数据结构的熟练使用。

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;
}
posted @ 2026-07-19 12:13  宰杀方向盘  阅读(1)  评论(0)    收藏  举报