分块思想

分块思想其实是一种暴力

还是 【线段树1】洛谷模板

我们可以把它分成 (sqrt n, sqrt n,..., sqrt n) 这样的一个一个块。

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e5 + 10, M = 350;
int id[N], w[N];
ll sum[M], lz[M];

int n, m, len;
void updt(int l, int r, int v) {
	if (id[l] == id[r]) {
		for (int i = l; i <= r; i++) w[i] += v, sum[id[i]] += v;
		return;
	}
	int i = l, j = r;
	while (id[i] == id[l])w[i] += v, sum[id[i]] += v, i++;
	while (id[j] == id[r])w[j] += v, sum[id[j]] += v, j--;

	for (int k = id[i]; k <= id[j]; k++)sum[k] += 1ll * len * v, lz[k] += v;
}
ll query(int l, int r) {
	ll res = 0;
	if (id[l] == id[r]) {
		for (int i = l; i <= r; i++) res += w[i] + lz[id[i]];
		return res;
	}
	int i = l, j = r;
	while (id[i] == id[l]) res += w[i] + lz[id[i]], i++;
	while (id[j] == id[r]) res += w[j] + lz[id[j]], j--;
	for (int k = id[i]; k <= id[j]; k++) res += sum[k];
	return res;
}
int main() {
	scanf("%d%d", &n, &m);
	len = sqrt(n);
	for (int i = 1; i <= n; i++) scanf("%d", w + i), id[i] = i / len, sum[id[i]] += w[i];

	while (m--) {
		int op, a, b, c;
		scanf("%d", &op);
		if (op == 1) {
			scanf("%d%d%d", &a, &b, &c);
			updt(a, b, c);
		}
		else {
			scanf("%d%d", &a, &b);
			printf("%lld
", query(a, b));
		}
	}
}
原文地址:https://www.cnblogs.com/sduwh/p/14000653.html