分块
分块是暴力修改的一种改进
本质是大块整体操作,小块暴力修改,使得时间复杂度控制在\(O(\sqrt{N})\)之内
首先把数组分成大约\(\sqrt{N}\)块,每一块确定两个端点
修改操作:
- 对于在一段之中的:
直接修改\(a、sum\)数组 - 对于跨段的:
整段的区间:直接打个增加标记\(add\),不去修改\(a、sum\)数组
左右的小段部分:依然修改\(a、sum\)数组
查询操作:、
- 对于在一段之中的:
直接累加\(a\)数组 - 对于跨段的:
整段的区间:直接把\(add\)标记乘以长度再加上\(sum\)数组
左右的小段部分:依然累加\(a\)数组和\(add\)标记乘以两端的长度
由此发现:\(sum\)一直是\(a\)的区间和,真正的\(A\)应该是数组\(a\)加上\(add\)
注意开\(ll\),把\(ll\)的数组放在前面乘
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std ;
typedef long long ll ;
const int N = 100010 ;
const int M = 2010 ;
int n, q, B ;
int pos[N], L[M], R[M] ;
ll a[N], sum[N], add[N] ;
char get() {
char ch = getchar() ;
while (!isalpha(ch)) ch = getchar() ;
return ch ;
}
void init() {
B = sqrt(n) ;
for (int i = 1; i <= B; i++) L[i] = (i - 1) * B + 1, R[i] = i * B ;
if (R[B] < n) B++, L[B] = R[B - 1] + 1, R[B] = n ;
for (int i = 1; i <= B; i++)
for (int j = L[i]; j <= R[i]; j++) {
pos[j] = i ;
sum[i] += a[j] ;
}
}
void modify(int l, int r, ll val) {
int p = pos[l], q = pos[r] ;
if (p == q) {
for (int i = l; i <= r; i++) a[i] += val ;
sum[p] += val * (r - l + 1) ;
} else {
for (int i = p + 1; i <= q - 1; i++) add[i] += val ;
for (int i = l; i <= R[p]; i++) a[i] += val ;
sum[p] += val * (R[p] - l + 1) ;
for (int i = L[q]; i <= r; i++) a[i] += val ;
sum[q] += val * (r - L[q] + 1) ;
}
}
ll query(int l, int r) {
int p = pos[l], q = pos[r] ;
ll 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() {
scanf("%d%d", &n, &q) ;
for (int i = 1; i <= n; i++) scanf("%lld", &a[i]) ;
init() ;
while (q--) {
char op = get() ;
if (op == 'C') {
int l, r, val ; scanf("%d%d%d", &l, &r, &val) ;
modify(l, r, val) ;
} else {
int l, r ; scanf("%d%d", &l, &r) ;
printf("%lld\n", query(l, r)) ;
}
}
}

浙公网安备 33010602011771号