段树2D,矩形之和

时间:2012-07-18 12:51:52

标签: c++ data-structures tree

我真的想学习并实现分段树2D,最后。它困扰着我。我知道段树的1D情况,但不知何故我无法用2D管理。问题是我有一个矩阵1024x1024(所以我使用数组[2048] [2048]作为树),我想实现两个操作:

  1. void insert(int x,int y,int val); - 将值val赋给矩阵的元素[x] [y]
  2. int query(int x1,int y1,int x2,int y2); - 返回矩形(x1,y1,x2,y2)
  3. 中矩阵元素的总和

    到目前为止,我写了这个:

    const int M=1024;
    int tree[2*M][2*M];
    
    void insert(int x, int y, int val) {
      int vx=M+x, vy=M+y;
      tree[vx][vy]=val;
      while(vy!=1) {
        vy/=2;
        tree[vx][vy]=tree[vx][2*vy]+tree[vx][2*vy+1];
      }
    
      while(vx!=1) {
        vy=M+y;
        vx/=2;
        while(vy!=1) {
          vy/=2;
          tree[vx][vy]=tree[2*vx][2*vy]+tree[2*vx+1][2*vy+1];
        }
      }
    }
    
    int query(int x1, int y1, int x2, int y2) {
      int vx1=M+x1, vy1=M+y1, vx2=M+x2, vy2=M+y2;  
      int res=tree[vx1][vy1];
      if(vx1!=vx2 || vy1!=vy2) res+=tree[vx2][vy2];
      while(vx1/2 != vx2/2) {
        vy1=M+y1; vy2=M+y2;
        while(vy1/2 != vy2/2) {
          if(vx1%2==0 && vy1%2==0) res+=tree[vx1+1][vy1+1];
          if(vx2%2==1 && vy2%2==1) res+=tree[vx2-1][vy2-1]; 
          vy1/=2; vy2/=2;
        }
        vx1/=2; vx2/=2;
      }
    
      return res;
    }
    

    但它无法正常工作。说,对于:

    插入(5,5,1); 查询(0,5,1000,5);

    它返回0,而不是1.我认为问题出在查询中(我希望插入没问题),我不完全理解这个操作的想法。在1D我没有问题,但对我来说这个案例很难想象。

    你能帮我正确实现吗?我非常感谢你的帮助。

    编辑:也许最好在1D中展示我是如何做到的,这段代码可行,我觉得这个想法很简单:

    const int M=1024;
    int tree[2*M]; 
    
    void insert(int x, int val) {
      int v=M+x;
      tree[v]=val;
      while(v!=1) {
        v/=2;
        tree[v]=tree[2*v]+tree[2*v+1];
      } 
    }
    
    int query(int a, int b) {
      int va=M+a, vb=M+b;
      int res=tree[va];
      if(va!=vb) res+=tree[vb];
      while(va/2 != vb/2) {
        if(va%2==0) res+=tree[va+1];
        if(vb%2==1) res+=tree[vb-1];
        va/=2; vb/=2;
      }
      return res;  
    }
    

    但不幸的是我无法在2D中使用它。

1 个答案:

答案 0 :(得分:0)

好吧,你的案例返回0的原因是只执行了这部分代码:

int res=tree[vx1][vy1];
if(vx1!=vx2 || vy1!=vy2)
    res+=tree[vx2][vy2];

此处res为0,因为tree[vx1][vy1]tree[vx2][vy2]在您的情况下均为零。

此部分不会更改res,因为从未满足条件:

if(vx1%2==0 && vy1%2==0)
    res+=tree[vx1+1][vy1+1];
if(vx2%2==1 && vy2%2==1)
    res+=tree[vx2-1][vy2-1];

因此,res值不会改变,仍然为0。

现在,关于整个事情。你正在以一种非常奇怪的方式构建一个分段树,实际上,你根本就没有构建任何树,而且很难理解你在使用该代码做了什么。通常,您希望将二叉树(分段树所在)实现为链接列表,其节点类似于:

struct node
{
    int data;
    node *left;        
    node *right;
};

我建议您查看hereherehereherehere,了解二元树和间隔树的信息和实现。