[BZOJ 3212] A Simple Problem with Integers 题解

考虑分块处理,(log(n)) 块长。目前的 Darkbzoj Top1,41ms无压力水过。

#pragma GCC optimize(3, "inline", "Ofast")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
long long a[100010], sum[20010], add[20010];
int L[20010], R[20010];
int pos[100010];
int n, m, t;
void change(int l, int r, long long d) {
	int p = pos[l], q = pos[r];
	if (p == q) {
		for (int i = l; i <= r; i++) a[i] += d;
		sum[p] += d*(r - l + 1);
	}else {
		for (int i = p + 1; i <= q - 1; i++) add[i] += d;
		for (int i = l; i <= R[p]; i++) a[i] += d;
		sum[p] += d*(R[p] - l + 1);
		for (int i = L[q]; i <= r; i++) a[i] += d;
		sum[q] += d*(r - L[q] + 1);
	}
}
long long ask(int l, int r) {
	int p = pos[l], q = pos[r];
	long long ans = 0;
	if (p == q) {
		for (int i = l; i <= r; i++) ans += a[i];
		ans += add[p] * (r - l + 1);
	}else {
		for (int i = p + 1; i <= q - 1; i++)ans += sum[i] + add[i] * (R[i] - L[i] + 1);
		for (int i = l; i <= R[p]; i++) ans += a[i];
		ans += add[p] * (R[p] - l + 1);
		for (int i = L[q]; i <= r; i++) ans += a[i];
		ans += add[q] * (r - L[q] + 1);
	}
	return ans;
}
int main() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
	t = log(n);
	for (int i = 1; i <= t; i++) {
		L[i] = (i - 1)* log(n) + 1;
		R[i] = i* log(n);
	}
	if (R[t] < n) t++, L[t] = R[t - 1] + 1, R[t] = n;
	for (int i = 1; i <= t; i++)for (int j = L[i]; j <= R[i]; j++)pos[j] = i,sum[i] += a[j];
	while (m--) {
		char op[3];
		int l, r, d;
		scanf("%s%d%d", op, &l, &r);
		if (op[0] == 'C') {
			scanf("%d", &d);
			change(l, r, d);
		}else printf("%lld
", ask(l, r));
	}
}
原文地址:https://www.cnblogs.com/Inversentropir-36/p/13290307.html