二维差分+树状数组。
定义差分数组$d_{i, j} = a_{i, j} + a_{i - 1, j - 1} - a_{i, j - 1} - a_{i - 1, j}$,有$a_{i, j} = \sum_{x = 1}^{i}\sum_{y = 1}^{j}d_{i, j}$。
我们要求$sum(n, m) = \sum_{i = 1}^{n}\sum_{j = 1}^{m}a_{i, j} $,
代入$a_{i, j}$,得$sum(n, m) = \sum_{i = 1}^{n}\sum_{j = 1}^{m}\sum_{x = 1}^{i}\sum_{y = 1}^{j}d_{x, y}$。
列一下发现$d_{x, y}$出现了$(n - x + 1) * (m - y + 1)$次。
那么$sum(n, m) = \sum_{i = 1}^{n}\sum_{j = 1}^{m}d_{i, j} * (n - i + 1) * (m - j + 1)$。
把$(n + 1),(m + 1),i, j$看作四项展开,得到$(n + 1) * (m + 1)\sum_{i = 1}^{n}\sum_{j = 1}^{m}d_{i, j} + \sum_{i = 1}^{n}\sum_{j = 1}^{m}d_{i, j} * i * j - (m + 1) \sum_{i = 1}^{n}\sum_{j = 1}^{m}d_{i, j} * i - (n + 1)\sum_{i = 1}^{n}\sum_{j = 1}^{m}d_{i, j} * j$。
两个$\sum$可以用一个二维树状数组维护,这样子维护四个树状数组即可(修改好长)。
时间复杂度$O(qlognlogm)$。
另外,longlong在Luogu上会MLE最后两个点,要用int
Code:
#include <cstdio> #include <cstring> using namespace std; typedef int ll;const int N = 2050;int n, m;template <typename T> inline void read(T &X) {X = 0; char ch = 0; T op = 1;for(; ch > '9'|| ch < '0'; ch = getchar())if(ch == '-') op = -1;for(; ch >= '0' && ch <= '9'; ch = getchar())X = (X << 3) + (X << 1) + ch - 48;X *= op; }struct BinaryIndexTree {ll arr[N][N];#define lowbit(p) (p & (-p))inline void modify(int x, int y, ll v) {for(int i = x; i <= n; i += lowbit(i))for(int j = y; j <= m; j += lowbit(j))arr[i][j] += v;}inline ll query(int x, int y) {ll res = 0LL;for(int i = x; i > 0; i -= lowbit(i))for(int j = y; j > 0; j -= lowbit(j))res += arr[i][j];return res;}} sum, mulij, muli, mulj;inline int min(int x, int y) {return x > y ? y : x; }inline int max(int x, int y) {return x > y ? x : y; }inline ll qSum(int x, int y) {return 1LL * (x + 1) * (y + 1) * sum.query(x, y) + 1LL * mulij.query(x, y) - 1LL * (y + 1) * muli.query(x, y) - 1LL * (x + 1) * mulj.query(x, y); }int main() { // freopen("Sample.txt", "r", stdin);char op = getchar();read(n), read(m);for(; ; ) {for(op = getchar(); op != 'L' && op != 'k' && op >= 0; op = getchar());if(op < 0) break;if(op == 'L') {int a, b, c, d; ll v;read(a), read(b), read(c), read(d), read(v);int lx = min(a, c), ly = min(b, d), rx = max(a, c), ry = max(b, d);sum.modify(lx, ly, v);sum.modify(rx + 1, ry + 1, v);sum.modify(lx, ry + 1, -v);sum.modify(rx + 1, ly, -v);muli.modify(lx, ly, v * lx);muli.modify(rx + 1, ry + 1, v * (rx + 1));muli.modify(lx, ry + 1, -v * lx);muli.modify(rx + 1, ly, -v * (rx + 1));mulj.modify(lx, ly, v * ly);mulj.modify(rx + 1, ry + 1, v * (ry + 1));mulj.modify(lx, ry + 1, -v * (ry + 1));mulj.modify(rx + 1, ly, -v * ly);mulij.modify(lx, ly, v * lx * ly);mulij.modify(rx + 1, ry + 1, v * (rx + 1) * (ry + 1));mulij.modify(lx, ry + 1, -v * (ry + 1) * lx);mulij.modify(rx + 1, ly, -v * (rx + 1) * ly);} else {int a, b, c, d;read(a), read(b), read(c), read(d);int lx = min(a, c), ly = min(b, d), rx = max(a, c), ry = max(b, d);printf("%d\n", qSum(rx, ry) + qSum(lx - 1, ly - 1) - qSum(rx, ly - 1) - qSum(lx - 1, ry));}}return 0; }