二维树状数组,区间修改,区间查询
对于区间$(x,y)$,用差分数组来维护,每次从$(1,1)$加到$(i,j)$
可以发现,$t[1][1]$被加了$x*y$次,$t[1][2]$被加了$(x-1)*y$次…
那么区间$(x,y)$的和即为
$∑i=(1,x)∑j=(1,y)$ $t[i][j]*(x-i+1)*(y-j+1)$
把括号打开
$∑i=(1,x)∑j=(1,y)$ $t[i][j]*(x+1)*(y+1) + t[i][j]*i*(y+1) + t[i][j]*j*(x+1) + t[i][j]*i*j$
所以维护四个数组,分别表示:$t[i][j],t[i][j]*i,t[i][j]*j,t[i][j]*i*j$
然后查询的时候,乘上对应的$x+1$和$y+1$。
修改一段区间$(x_1-x_2,y_1-y_2)$时,则有
$+(x_1,y_2),-(x_2+1,y_1),-(x_1,y_2+1),+(x_2+1,y_2+1)$
查询一段区间$(x_1-x_2,y_1-y_2)$时,则有
$+(x_1-1,y_2-1),-(x_2,y_1-1),-(x_1-1,y_2),+(x_2,y_2)$
代码如下...
#include<cstdio> #include<iostream> #include<cmath> #include<cstring> #define MogeKo qwq using namespace std; int n,m,a,b,c,d,k; int t[5][2050][2050]; char op; int read() { int x = 0,f = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar(); } while('0' <= ch && ch <= '9') { x = (x<<3)+(x<<1) + ch-'0'; ch = getchar(); } return x * f; } int lowbit(int x) { return x & (-x); } void update(int x,int y,int k) { for(int i = x; i <= n; i += lowbit(i)) for(int j = y; j <= m; j += lowbit(j)) { t[1][i][j] += k; t[2][i][j] += k * x; t[3][i][j] += k * y; t[4][i][j] += k * x * y; } } int query(int x,int y) { int ret = 0; for(int i = x; i; i -= lowbit(i)) for(int j = y; j; j -= lowbit(j)) { ret += t[1][i][j] * (x+1) * (y+1); ret -= t[2][i][j] * (y+1); ret -= t[3][i][j] * (x+1); ret += t[4][i][j]; } return ret; } void getupdate(int a,int b,int c,int d,int k) { update(c+1,d+1,k); update(c+1,b,-k); update(a,d+1,-k); update(a,b,k); } int getquery(int a,int b,int c,int d) { return query(c,d) - query(c,b-1) - query(a-1,d) + query(a-1,b-1); } int main() { scanf("%c%d%d",&op,&n,&m); while(cin >> op) { a = read(),b = read(),c = read(),d = read(); if(op == 'L') { k = read(); getupdate(a,b,c,d,k); } if(op == 'k') printf("%d ",getquery(a,b,c,d)); } return 0; }