zoukankan      html  css  js  c++  java
  • 二维树状数组

    二维树状数组可以实现在平面上的区域加、区域查询等操作。

    区域修改

    我们在一维时维护树状数组的区间操作时,对其进行了差分。类比一维的思想,我们在二维平面上也对树状数组差分。

    我们来看二维的前缀和:

    [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)-d(i-1,j)-d(i,j-1)+d(i-1,j-1) ]

    (发现了吧,这其实就是)

    比如我们有一下这个全为 (0) 的矩阵,那么给中间 (2 imes 3) 的矩阵差分后长成这样:(“o” 表示操作区域)

    0 0 0 0 0    0 0 0 0 0
    0 o o o 0 -> 0 +x 0 0 -x
    0 o o o 0    0 0 0 0 0
    0 0 0 0 0    0 -x 0 0 +x
    

    这样我们就简单地完成了区域加的操作。

    区域查询

    根据差分数组的定义,我们不难发现,对于点 ((x,y)) ,它的二维前缀和就是:

    [sum_{i=1}^xsum_{j=1}^ysum_{h=1}^isum_{k=1}^j d[h][k] ]

    但我们类比一下一维树状数组的区间求和,我们亦可以统计每个 (d[h][k]) 出现的次数,我们就可以发现 (d[1][1]) 出现了 ((x imes y)) 次,(d[1][2]) 出现了 (x imes(y-1)) 次……(d[h][k]) 出现了 ((x-h+1) imes (y-k+1)) 次。

    则原式整理得:

    [sum_{i=1}^xsum_{j=1}^y d[i][j] imes (x-i+1) imes (y-j+1) ]

    分解得:

    [sum_{i=1}^xsum_{j=1}^y d[i][j] imes [(xy-xj+x)+(-yi+ij-i)+(y-j+1)] ]

    最后得:

    [sum_{i=1}^xsum_{j=1}^y d[i][j] imes (xy+x+y+1)-d[i][j] imes i(y+1)-d[i][j] imes j(x+1)+d[i][j] imes i imes j ]

    根据我们最后分解出来的公式,我们需要维护四个数组 (d[i][j],d[i][j] imes i,d[i][j] imes j,d[i][j] imes i imes j) ,从而实现区间查询。

    例题 — P4514 上帝造题的七分钟

    即二维树状数组裸题。

    $ exttt{code}$
    #define Maxn 2050
    int n,m,tree[Maxn][Maxn][4];
    inline void add(int x,int y,int k)
    {
    	 int a=k,b=k*x,c=k*y,d=k*x*y;
    	 for(int i=x;i<=n;i+=i&(-i))
    	 	 for(int j=y;j<=m;j+=j&(-j))
    	 	 {
    	 	 	 tree[i][j][0]+=a;
    	 	 	 tree[i][j][1]+=b;
    	 	 	 tree[i][j][2]+=c;
    	 	 	 tree[i][j][3]+=d;
    		 }
    }
    inline int query(int x,int y)
    {
    	 int ret=0,a=x*y+x+y+1,b=y+1,c=x+1,d=1;
    	 for(int i=x;i;i-=i&(-i))
    	 	 for(int j=y;j;j-=j&(-j))
    	 	 {
    	 	 	 ret+=tree[i][j][0]*a;
    	 	 	 ret-=tree[i][j][1]*b;
    	 	 	 ret-=tree[i][j][2]*c;
    	 	 	 ret+=tree[i][j][3]*d;
    		 }
    	 return ret;
    }
    
    if(修改) add(a,b,x),add(a,d+1,-x),add(c+1,b,-x),add(c+1,d+1,x);
    else printf("%d
    ",query(c,d)-query(a-1,d)-query(c,b-1)+query(a-1,b-1));
    

    参考文章

  • 相关阅读:
    佛洛依德
    Python2.7利用Tesseract进行中英文图像识别
    批量生成二维码打包成exe文件
    python基础5—文件 | json序列化
    python基础6—(高阶,匿名,偏)函数 | 装饰器
    python基础4—面向对象
    python基础2—集合框架
    一不小心翻车了-(angularjs 1.6X) 由Eventbus使用异常说起
    简单说下js闭包之setTimeout
    html5上传本地图片,在线预览及裁剪(filereader,canvas)
  • 原文地址:https://www.cnblogs.com/EricQian/p/15375842.html
Copyright © 2011-2022 走看看