【洛谷P4514】上帝造题的七分钟
作者:互联网
Description
给定一个矩阵,要求实现区间修改,区间求和的操作
Solution
二维树状数组的模板题,类比一维,我们依旧利用差分的思想完成。
首先,运用简单的容斥思想,二维前缀和sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j]
查询左上角点(x1,y1),右下角点(x2,y2)的区间和则是sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1]
那么我们用树状数组维护差分数组即可。
具体地,根据差分数组的含义,对于点(x,y),他的前缀和是
$$\sum\limits_{i=1}^{x}\sum\limits_{j=1}^{y}\sum\limits_{k=1}^{i}\sum\limits_{l=1}^{j}{d[k][l]}$$
化简,得
$$\sum\limits_{i=1}^{x}\sum\limits_{j=1}^{y}{d[i][j](x-i+1)(y-j+1)}$$
分解,得
$$\sum\limits_{i=1}^{x}\sum\limits_{j=1}^{y}{d[i][j](xy+x+y+1)-d[i][j]i(y+1)-d[i][j]j(x+1)+d[i][j]ij}$$
根据这个式子,我们维护四个树状数组d[i][j],d[i][j]i,d[i][j]j,d[i][j]ij即可
Code
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 typedef long long ll; 7 inline int read() { 8 int ret = 0, op = 1; 9 char c = getchar(); 10 while (!isdigit(c)) { 11 if (c == '-') op = -1; 12 c = getchar(); 13 } 14 while (isdigit(c)) { 15 ret = ret * 10 + c - '0'; 16 c = getchar(); 17 } 18 return ret * op; 19 } 20 int n, m; 21 struct BIT { 22 int a[2050][2050]; 23 inline int lowbit(int x) { 24 return x & (-x); 25 } 26 int query(int x, int y) { 27 int ret = 0; 28 for (register int i = x; i >= 1; i -= lowbit(i)) 29 for (register int j = y; j >= 1; j -= lowbit(j)) 30 ret += a[i][j]; 31 return ret; 32 } 33 void add(int x, int y, int val) { 34 for (register int i = x; i <= n; i += lowbit(i)) 35 for (register int j = y; j <= m; j += lowbit(j)) 36 a[i][j] += val; 37 } 38 } A, Ai, Aj, Aij; 39 void add(int x, int y, int val) { 40 A.add(x, y, val); 41 Ai.add(x, y, val * x); 42 Aj.add(x, y, val * y); 43 Aij.add(x, y, val * x * y); 44 } 45 int query(int x, int y) { 46 return A.query(x, y) * (x * y + x + y + 1) - Ai.query(x, y) * (y + 1) - Aj.query(x, y) * (x + 1) + Aij.query(x, y); 47 } 48 int main() { 49 getchar(); 50 n = read(); m = read(); 51 char op[3]; 52 while (~scanf("%s", op)) { 53 int x1 = read(), y1 = read(), x2 = read(), y2 = read(); 54 if (op[0] == 'L') { 55 int z = read(); 56 add(x1, y1, z); 57 add(x1, y2 + 1, -z); 58 add(x2 + 1, y1, -z); 59 add(x2 + 1, y2 + 1, z); 60 } 61 else printf("%d\n", query(x2, y2) - query(x1 - 1, y2) - query(x2, y1 - 1) + query(x1 - 1, y1 - 1)); 62 } 63 return 0; 64 }AC Code
标签:洛谷,limits,int,sum,ret,七分钟,数组,造题,include 来源: https://www.cnblogs.com/shl-blog/p/11285222.html