二维树状数组
设 \(s\) 为前缀和数组,\(d\) 为差分数组,\(a\) 为原数组。
则:
\[s_{n,m}=\sum\limits_{i=1}^n\sum\limits_{j=1}^ma_{i,j}
\]
有:
\[a_{i,j}=\sum\limits_{k=1}^n\sum\limits_{l=1}^jd_{k,l}
\]
所以:
\[s_{n,m}=\sum\limits_{i=1}^n\sum\limits_{j=1}^m\sum\limits_{k=1}^i\sum\limits_{l=1}^jd_{i,j}
\]
发现 \(d_{1,1}\) 出现 \(n\times m\) 次,\(d_{1,2}\) 出现 \(n\times (m-1)\) 次,\(d_{2,2}\) 出现 \((n-1)\times (m-1)\) 次,\(\cdots\),总结规律,发现 \(d_{x,y}\) 出现 \((n-x+1)\times (m-y+1)\) 次。
所以原式变为:$$s_{n,m}=\sum\limits_{i=1}^n \sum\limits_{j=1}^m (n-i+1) \times (m-j+1) \times d_{i,j}$$
展开:
\[s_{n,m}=\sum\limits_{i=1}^n \sum\limits_{j=1}^m(nm - nj + n - mi + ij - i + m - j + 1)
\]
合并同类项:
\[s_{n,m}=\sum\limits_{i=1}^n \sum\limits_{j=1}^m[nm-m(i - 1) - n(j - 1) + (i - 1)(j - 1)]
\]
展开:
\[s_{n,m}=\sum\limits_{i=1}^n \sum\limits_{j=1}^m nm \times d_{i,j}-\sum\limits_{i=1}^n \sum\limits_{j=1}^m m(i-1) \times d_{i,j} - \sum\limits_{i=1}^n \sum\limits_{j=1}^m n(j-1) \times d_{i,j} + \sum\limits_{i=1}^n \sum\limits_{j=1}^m (i-1)(j-1) \times d_{i,j}
\]
所以二维树状数组维护 \(d_{i,j},(i-1) \times d_{i,j},(j-1) \times d_{i,j}, (i-1)(j-1) \times d_{i,j}\) 就可以了。
修改的话,二维差分即可。查询同理。因为二维树状数组和一维数状数组一样维护的是前缀和。
#include <bits/stdc++.h>
using namespace std;
const int N = (1 << 11) + 1;
int n, m, f1[N][N], f2[N][N], f3[N][N], f4[N][N];
char c, opt;
int lowbit(int x) {
return x & -x;
}
void add(int x, int y, int k) {
for (int i = x; i <= n; i += lowbit(i)) {
for (int j = y; j <= m; j += lowbit(j)) {
f1[i][j] += k;
f2[i][j] += (x - 1) * k;
f3[i][j] += (y - 1) * k;
f4[i][j] += (x - 1) * (y - 1) * k;
}
}
}
int getsum(int x, int y) {
int sum = 0;
for (int i = x; i; i -= lowbit(i)) {
for (int j = y; j; j -= lowbit(j)) {
sum += f1[i][j] * x * y;
sum -= f2[i][j] * y;
sum -= f3[i][j] * x;
sum += f4[i][j];
}
}
return sum;
}
int main() {
cin >> c >> n >> m;
while (cin >> opt) {
int a, b, c, d, val;
if (opt == 'L') {
cin >> a >> b >> c >> d >> val;
add(a, b, val);
add(a, d + 1, -val);
add(c + 1, b, -val);
add(c + 1, d + 1, val);
} else {
cin >> a >> b >> c >> d;
cout << getsum(c, d) - getsum(a - 1, d) - getsum(c, b - 1) + getsum(a - 1, b - 1) << endl;
}
}
return 0;
}

浙公网安备 33010602011771号