二维树状数组+差分【p4514】上帝造题的七分钟
Description
“第一分钟,X说,要有矩阵,于是便有了一个里面写满了\(0\)的\(n\times m\)矩阵。
第二分钟,L说,要能修改,于是便有了将左上角为\((a,b)\),右下角为\((c,d)\)的一个矩形区域内的全部数字加上一个值的操作。
第三分钟,k说,要能查询,于是便有了求给定矩形区域内的全部数字和的操作。
第四分钟,彩虹喵说,要基于二叉树的数据结构,于是便有了数据范围。
第五分钟,和雪说,要有耐心,于是便有了时间限制。
第六分钟,吃钢琴男说,要省点事,于是便有了保证运算过程中及最终结果均不超过32位有符号整数类型的表示范围的限制。
第七分钟,这道题终于造完了,然而,造题的神牛们再也不想写这道题的程序了。”
——《上帝造裸题的七分钟》 所以这个神圣的任务就交给你了。
Input
输入数据的第一行为
X n m,代表矩阵大小为\(n \times m\)。
从输入数据的第二行开始到文件尾的每一行会出现以下两种操作:
L a b c d delta—— 代表将\((a,b),(c,d)\)为顶点的矩形区域内的所有数字加上delta。 k a b c d—— 代表求\((a,b),(c,d)\)为顶点的矩形区域内所有数字的和。请注意,\(k\)为小写。
Output
针对每个k操作,在单独的一行输出答案。
裸的二维树状数组问题.
二维前缀和:
\[
sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j]
\]
考虑差分:
\[
d[i][j]表示a[i][j]与a[i-1][j]+a[i][j-1]-a[i-1][j-1]的差
\]
此时小推一下式子即可.
区间修改,区间查询:
\[
\sum_{i=1}^{x}\sum_{j=1}^{y}\sum_{k=1}^{i}\sum_{h=1}^{j}d[h][k]
\]
这个时候记录每个位置的\(d[h][k]\)出现了几次.
所以式子变形得到.
\[
\sum_{i=1}^{x}\sum_{j=1}^{y}d[i][j] \times (x-i+1) \times (y-j+1)
\]
然后把式子展开.就变成这个
\[
(x+1)\times (y+1)\times \sum_{i=1}^{x}\sum_{j=1}^{y}d[i][j]-(y+1)\times\sum_{i=1}^{x}\sum_{j=1}^{y}d[i][j]\times i -(x+1)\sum_{i=1}^{x}\sum_{j=1}^{y}d[i][j]\times j + \sum_{i=1}^{x}\sum_{j=1}^{y}d[i][j] \times i \times j
\]
然后四个树状数组数组分别维护这些东西:
\(d[i][j],d[i][j]\times i ,d[i][j] \times j,d[i][j] \times i\times j\)
代码
#include<cstdio> #include<cctype> #define N 2050 #define R register using namespace std; inline void in(int &x) { int f=1;x=0;char s=getchar(); while(!isdigit(s)){if(s=='-')f=-1;s=getchar();} while(isdigit(s)){x=x*10+s-'0';s=getchar();} x*=f; } int t1 ,t2 ,t3 ,t4 ,n,m; #define lowbit(x) x&-x inline void add(int x,int y,int del) { for(R int i=x;i<=n;i+=lowbit(i)) for(R int j=y;j<=m;j+=lowbit(j)) { t1[i][j]+=del; t2[i][j]+=del*x; t3[i][j]+=del*y; t4[i][j]+=del*x*y; } } inline void ado(int xa,int ya,int xb,int yb,int z) {add(xa,ya,z);add(xa,yb+1,-z);add(xb+1,ya,-z);add(xb+1,yb+1,z);} inline int que(int x,int y) { R int res=0; for(R int i=x;i;i-=lowbit(i)) for(R int j=y;j;j-=lowbit(j)) res+=(x+1)*(y+1)*t1[i][j]-(y+1)*t2[i][j]-(x+1)*t3[i][j]+t4[i][j]; return res; } inline int query(int xa,int ya,int xb,int yb) {return que(xb,yb)-que(xb,ya-1)-que(xa-1,yb)+que(xa-1, ya-1);} char s[6]; int main() { in(n),in(m); for(R int a,b,c,d,x;~scanf("%s",s+1);) { in(a),in(b),in(c),in(d); if(s[1]=='L')in(x),ado(a,b,c,d,x); else printf("%d\n",query(a,b,c,d)); } }
- BZOJ 3132: 上帝造题的七分钟【树状数组(二维区间加,区间查询
- 二维树状数组的区间加减及查询 tyvj 1716 上帝造题的七分钟
- [TYVJ P1716/BZOJ 3132 上帝造题的七分钟] 二维树状数组区间修改、区间查询
- [bzoj3132]上帝造题的七分钟——二维树状数组
- 【bzoj3132】上帝造题的七分钟 二维树状数组区间修改区间查询
- 二维树状数组的区间加减及查询 tyvj 1716 上帝造题的七分钟
- bzoj 3132 上帝造题的七分钟(二维树状数组区间修改区间查询模板)
- BZOJ 3132 上帝造题的七分钟(二维树状数组)
- bzoj 3132: 上帝造题的七分钟 (二维树状数组)
- 二维树状数组总结&&【洛谷P4514】 上帝造题的七分钟
- bzoj3132上帝造题的七分钟 二维树状数组
- BZOJ3132 上帝造题的七分钟 【二维树状数组】
- tyvj P1716 - 上帝造题的七分钟 二维树状数组区间查询及修改 二维线段树
- 【BZOJ 3132】上帝造题的七分钟【二维树状数组】
- BZOJ3132 上帝造题的七分钟 【二维树状数组】
- 【BZOJ3132】【TYVJ1716】上帝造题的七分钟 二维树状数组
- 【bzoj 3132】上帝造题的七分钟(二维树状数组)
- 3132: 上帝造题的七分钟 树状数组 二维区间加减+查询
- BZOJ 3132: 上帝造题的七分钟( 二维BIT )
- BZOJ 3038 上帝造题的七分钟2