Luogu 4514 上帝造题的七分钟
二维差分+树状数组。
定义差分数组$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; }