Arbre indexé binaire bidimensionnel ou arbre Fenwick

Arbre indexé binaire bidimensionnel ou arbre Fenwick

Prérequis - Arbre Fenwick

Nous savons que pour répondre efficacement aux requêtes de somme de plage sur un tableau 1D, l'arbre à index binaire (ou arbre de Fenwick) est le meilleur choix (encore meilleur que l'arbre à segments en raison de moins de besoins en mémoire et un peu plus rapide que l'arbre à segments).

Pouvons-nous répondre efficacement aux requêtes de somme de sous-matrice en utilisant l'arbre indexé binaire ?

La réponse est Oui . Ceci est possible en utilisant un BITS 2D qui n'est rien d'autre qu'un tableau de BIT 1D. 



Algorithme:

Nous considérons l'exemple ci-dessous. Supposons que nous devions trouver la somme de tous les nombres à l’intérieur de la zone en surbrillance :

arbre fenwick

Nous supposons l'origine de la matrice en bas - O. Ensuite, un BIT 2D exploite le fait que -

 Sum under the marked area = Sum(OB) - Sum(OD) - Sum(OA) + Sum(OC)   

Arbre indexé binaire bidimensionnel ou arbre Fenwick

Dans notre programme, nous utilisons la fonction getSum(x y) qui trouve la somme de la matrice de (0 0) à (x y). 
D'où la formule ci-dessous : 

 Sum under the marked area = Sum(OB) - Sum(OD) - Sum(OA) + Sum(OC) The above formula gets reduced to Query(x1y1x2y2) = getSum(x2 y2) - getSum(x2 y1-1) - getSum(x1-1 y2) + getSum(x1-1 y1-1)   

où 
x1 y1 = coordonnées x et y de C 
x2 y2 = coordonnées x et y de B
La fonction updateBIT(x y val) met à jour tous les éléments de la région – (x y) vers (N M) où 
N = coordonnée X maximale de toute la matrice. 
M = coordonnée Y maximale de toute la matrice.
La procédure de repos est assez similaire à celle de l'arbre indexé binaire 1D.

Vous trouverez ci-dessous l'implémentation C++ de l'arbre indexé 2D 

C++
   /* C++ program to implement 2D Binary Indexed Tree   2D BIT is basically a BIT where each element is another BIT.   Updating by adding v on (x y) means it's effect will be found   throughout the rectangle [(x y) (max_x max_y)]   and query for (x y) gives you the result of the rectangle   [(0 0) (x y)] assuming the total rectangle is   [(0 0) (max_x max_y)]. So when you query and update on   this BITyou have to be careful about how many times you are   subtracting a rectangle and adding it. Simple set union formula   works here.   So if you want to get the result of a specific rectangle   [(x1 y1) (x2 y2)] the following steps are necessary:   Query(x1y1x2y2) = getSum(x2 y2)-getSum(x2 y1-1) -    getSum(x1-1 y2)+getSum(x1-1 y1-1)   Here 'Query(x1y1x2y2)' means the sum of elements enclosed   in the rectangle with bottom-left corner's co-ordinates   (x1 y1) and top-right corner's co-ordinates - (x2 y2)   Constraints -> x1 <=x2 and y1 <=y2    /    y |    | --------(x2y2)    | | |    | | |    | | |    | ---------    | (x1y1)    |    |___________________________    (0 0) x-->   In this program we have assumed a square matrix. The   program can be easily extended to a rectangular one. */   #include       using     namespace     std  ;   #define N 4   // N-->max_x and max_y   // A structure to hold the queries   struct     Query   {      int     x1       y1  ;     // x and y co-ordinates of bottom left      int     x2       y2  ;     // x and y co-ordinates of top right   };   // A function to update the 2D BIT   void     updateBIT  (  int     BIT  [][  N  +  1  ]     int     x       int     y       int     val  )   {      for     (;     x      <=     N  ;     x     +=     (  x     &     -  x  ))      {      // This loop update all the 1D BIT inside the      // array of 1D BIT = BIT[x]      for     (  int     yy  =  y  ;     yy      <=     N  ;     yy     +=     (  yy     &     -  yy  ))      BIT  [  x  ][  yy  ]     +=     val  ;      }      return  ;   }   // A function to get sum from (0 0) to (x y)   int     getSum  (  int     BIT  [][  N  +  1  ]     int     x       int     y  )   {      int     sum     =     0  ;      for  (;     x     >     0  ;     x     -=     x  &-  x  )      {      // This loop sum through all the 1D BIT      // inside the array of 1D BIT = BIT[x]      for  (  int     yy  =  y  ;     yy     >     0  ;     yy     -=     yy  &-  yy  )      {      sum     +=     BIT  [  x  ][  yy  ];      }      }      return     sum  ;   }   // A function to create an auxiliary matrix   // from the given input matrix   void     constructAux  (  int     mat  [][  N  ]     int     aux  [][  N  +  1  ])   {      // Initialise Auxiliary array to 0      for     (  int     i  =  0  ;     i   <=  N  ;     i  ++  )      for     (  int     j  =  0  ;     j   <=  N  ;     j  ++  )      aux  [  i  ][  j  ]     =     0  ;      // Construct the Auxiliary Matrix      for     (  int     j  =  1  ;     j   <=  N  ;     j  ++  )      for     (  int     i  =  1  ;     i   <=  N  ;     i  ++  )      aux  [  i  ][  j  ]     =     mat  [  N  -  j  ][  i  -1  ];      return  ;   }   // A function to construct a 2D BIT   void     construct2DBIT  (  int     mat  [][  N  ]     int     BIT  [][  N  +  1  ])   {      // Create an auxiliary matrix      int     aux  [  N  +  1  ][  N  +  1  ];      constructAux  (  mat       aux  );      // Initialise the BIT to 0      for     (  int     i  =  1  ;     i   <=  N  ;     i  ++  )      for     (  int     j  =  1  ;     j   <=  N  ;     j  ++  )      BIT  [  i  ][  j  ]     =     0  ;      for     (  int     j  =  1  ;     j   <=  N  ;     j  ++  )      {      for     (  int     i  =  1  ;     i   <=  N  ;     i  ++  )      {      // Creating a 2D-BIT using update function      // everytime we/ encounter a value in the      // input 2D-array      int     v1     =     getSum  (  BIT       i       j  );      int     v2     =     getSum  (  BIT       i       j  -1  );      int     v3     =     getSum  (  BIT       i  -1       j  -1  );      int     v4     =     getSum  (  BIT       i  -1       j  );      // Assigning a value to a particular element      // of 2D BIT      updateBIT  (  BIT       i       j       aux  [  i  ][  j  ]  -  (  v1  -  v2  -  v4  +  v3  ));      }      }      return  ;   }   // A function to answer the queries   void     answerQueries  (  Query     q  []     int     m       int     BIT  [][  N  +  1  ])   {      for     (  int     i  =  0  ;     i   <  m  ;     i  ++  )      {      int     x1     =     q  [  i  ].  x1     +     1  ;      int     y1     =     q  [  i  ].  y1     +     1  ;      int     x2     =     q  [  i  ].  x2     +     1  ;      int     y2     =     q  [  i  ].  y2     +     1  ;      int     ans     =     getSum  (  BIT       x2       y2  )  -  getSum  (  BIT       x2       y1  -1  )  -      getSum  (  BIT       x1  -1       y2  )  +  getSum  (  BIT       x1  -1       y1  -1  );      printf     (  'Query(%d %d %d %d) = %d  n  '        q  [  i  ].  x1       q  [  i  ].  y1       q  [  i  ].  x2       q  [  i  ].  y2       ans  );      }      return  ;   }   // Driver program   int     main  ()   {      int     mat  [  N  ][  N  ]     =     {{  1       2       3       4  }      {  5       3       8       1  }      {  4       6       7       5  }      {  2       4       8       9  }};      // Create a 2D Binary Indexed Tree      int     BIT  [  N  +  1  ][  N  +  1  ];      construct2DBIT  (  mat       BIT  );      /* Queries of the form - x1 y1 x2 y2    For example the query- {1 1 3 2} means the sub-matrix-    y    /    3 | 1 2 3 4 Sub-matrix    2 | 5 3 8 1 {1132} ---> 3 8 1    1 | 4 6 7 5 6 7 5    0 | 2 4 8 9    |    --|------ 0 1 2 3 ----> x    |    Hence sum of the sub-matrix = 3+8+1+6+7+5 = 30    */      Query     q  []     =     {{  1       1       3       2  }     {  2       3       3       3  }     {  1       1       1       1  }};      int     m     =     sizeof  (  q  )  /  sizeof  (  q  [  0  ]);      answerQueries  (  q       m       BIT  );      return  (  0  );   }   
Java
   /* Java program to implement 2D Binary Indexed Tree    2D BIT is basically a BIT where each element is another BIT.    Updating by adding v on (x y) means it's effect will be found    throughout the rectangle [(x y) (max_x max_y)]    and query for (x y) gives you the result of the rectangle    [(0 0) (x y)] assuming the total rectangle is    [(0 0) (max_x max_y)]. So when you query and update on    this BITyou have to be careful about how many times you are    subtracting a rectangle and adding it. Simple set union formula    works here.    So if you want to get the result of a specific rectangle    [(x1 y1) (x2 y2)] the following steps are necessary:    Query(x1y1x2y2) = getSum(x2 y2)-getSum(x2 y1-1) -     getSum(x1-1 y2)+getSum(x1-1 y1-1)    Here 'Query(x1y1x2y2)' means the sum of elements enclosed    in the rectangle with bottom-left corner's co-ordinates    (x1 y1) and top-right corner's co-ordinates - (x2 y2)    Constraints -> x1 <=x2 and y1 <=y2     /    y |     | --------(x2y2)     | | |     | | |     | | |     | ---------     | (x1y1)     |     |___________________________    (0 0) x-->    In this program we have assumed a square matrix. The    program can be easily extended to a rectangular one. */   class   GFG   {      static     final     int     N     =     4  ;     // N-.max_x and max_y    // A structure to hold the queries    static     class   Query      {         int     x1       y1  ;     // x and y co-ordinates of bottom left       int     x2       y2  ;     // x and y co-ordinates of top right       public     Query  (  int     x1       int     y1       int     x2       int     y2  )      {      this  .  x1     =     x1  ;      this  .  y1     =     y1  ;      this  .  x2     =     x2  ;      this  .  y2     =     y2  ;      }       };      // A function to update the 2D BIT    static     void     updateBIT  (  int     BIT  [][]       int     x        int     y       int     val  )      {         for     (;     x      <=     N  ;     x     +=     (  x     &     -  x  ))         {         // This loop update all the 1D BIT inside the       // array of 1D BIT = BIT[x]       for     (;     y      <=     N  ;     y     +=     (  y     &     -  y  ))         BIT  [  x  ][  y  ]     +=     val  ;         }         return  ;      }      // A function to get sum from (0 0) to (x y)    static     int     getSum  (  int     BIT  [][]       int     x       int     y  )      {         int     sum     =     0  ;         for  (;     x     >     0  ;     x     -=     x  &-  x  )         {         // This loop sum through all the 1D BIT       // inside the array of 1D BIT = BIT[x]       for  (;     y     >     0  ;     y     -=     y  &-  y  )         {         sum     +=     BIT  [  x  ][  y  ]  ;         }         }         return     sum  ;      }      // A function to create an auxiliary matrix    // from the given input matrix    static     void     constructAux  (  int     mat  [][]       int     aux  [][]  )      {         // Initialise Auxiliary array to 0       for     (  int     i     =     0  ;     i      <=     N  ;     i  ++  )         for     (  int     j     =     0  ;     j      <=     N  ;     j  ++  )         aux  [  i  ][  j  ]     =     0  ;         // Construct the Auxiliary Matrix       for     (  int     j     =     1  ;     j      <=     N  ;     j  ++  )         for     (  int     i     =     1  ;     i      <=     N  ;     i  ++  )         aux  [  i  ][  j  ]     =     mat  [  N     -     j  ][  i     -     1  ]  ;         return  ;      }      // A function to construct a 2D BIT    static     void     construct2DBIT  (  int     mat  [][]        int     BIT  [][]  )      {         // Create an auxiliary matrix       int     [][]  aux     =     new     int  [  N     +     1  ][  N     +     1  ]  ;         constructAux  (  mat       aux  );         // Initialise the BIT to 0       for     (  int     i     =     1  ;     i      <=     N  ;     i  ++  )         for     (  int     j     =     1  ;     j      <=     N  ;     j  ++  )         BIT  [  i  ][  j  ]     =     0  ;         for     (  int     j     =     1  ;     j      <=     N  ;     j  ++  )         {         for     (  int     i     =     1  ;     i      <=     N  ;     i  ++  )         {         // Creating a 2D-BIT using update function       // everytime we/ encounter a value in the       // input 2D-array       int     v1     =     getSum  (  BIT       i       j  );         int     v2     =     getSum  (  BIT       i       j     -     1  );         int     v3     =     getSum  (  BIT       i     -     1       j     -     1  );         int     v4     =     getSum  (  BIT       i     -     1       j  );         // Assigning a value to a particular element       // of 2D BIT       updateBIT  (  BIT       i       j       aux  [  i  ][  j  ]     -         (  v1     -     v2     -     v4     +     v3  ));         }         }         return  ;      }      // A function to answer the queries    static     void     answerQueries  (  Query     q  []       int     m       int     BIT  [][]  )      {         for     (  int     i     =     0  ;     i      <     m  ;     i  ++  )         {         int     x1     =     q  [  i  ]  .  x1     +     1  ;         int     y1     =     q  [  i  ]  .  y1     +     1  ;         int     x2     =     q  [  i  ]  .  x2     +     1  ;         int     y2     =     q  [  i  ]  .  y2     +     1  ;         int     ans     =     getSum  (  BIT       x2       y2  )     -      getSum  (  BIT       x2       y1     -     1  )     -         getSum  (  BIT       x1     -     1       y2  )     +      getSum  (  BIT       x1     -     1       y1     -     1  );         System  .  out  .  printf  (  'Query(%d %d %d %d) = %dn'           q  [  i  ]  .  x1       q  [  i  ]  .  y1       q  [  i  ]  .  x2       q  [  i  ]  .  y2       ans  );         }         return  ;      }      // Driver Code   public     static     void     main  (  String  []     args  )      {         int     mat  [][]     =     {     {  1       2       3       4  }         {  5       3       8       1  }         {  4       6       7       5  }         {  2       4       8       9  }     };         // Create a 2D Binary Indexed Tree       int     [][]  BIT     =     new     int  [  N     +     1  ][  N     +     1  ]  ;         construct2DBIT  (  mat       BIT  );         /* Queries of the form - x1 y1 x2 y2     For example the query- {1 1 3 2} means the sub-matrix-     y     /     3 | 1 2 3 4 Sub-matrix     2 | 5 3 8 1 {1132} --. 3 8 1     1 | 4 6 7 5 6 7 5     0 | 2 4 8 9     |     --|------ 0 1 2 3 ---. x     |         Hence sum of the sub-matrix = 3+8+1+6+7+5 = 30     */      Query     q  []     =     {  new     Query  (  1       1       3       2  )         new     Query  (  2       3       3       3  )         new     Query  (  1       1       1       1  )};         int     m     =     q  .  length  ;         answerQueries  (  q       m       BIT  );      }   }      // This code is contributed by 29AjayKumar   
Python3
   '''Python3 program to implement 2D Binary Indexed Tree        2D BIT is basically a BIT where each element is another BIT.    Updating by adding v on (x y) means it's effect will be found    throughout the rectangle [(x y) (max_x max_y)]    and query for (x y) gives you the result of the rectangle    [(0 0) (x y)] assuming the total rectangle is    [(0 0) (max_x max_y)]. So when you query and update on    this BITyou have to be careful about how many times you are    subtracting a rectangle and adding it. Simple set union formula    works here.        So if you want to get the result of a specific rectangle    [(x1 y1) (x2 y2)] the following steps are necessary:        Query(x1y1x2y2) = getSum(x2 y2)-getSum(x2 y1-1) -     getSum(x1-1 y2)+getSum(x1-1 y1-1)        Here 'Query(x1y1x2y2)' means the sum of elements enclosed    in the rectangle with bottom-left corner's co-ordinates    (x1 y1) and top-right corner's co-ordinates - (x2 y2)        Constraints -> x1 <=x2 and y1 <=y2         /    y |     | --------(x2y2)     | | |     | | |     | | |     | ---------     | (x1y1)     |     |___________________________    (0 0) x-->        In this program we have assumed a square matrix. The    program can be easily extended to a rectangular one. '''   N   =   4   # N-.max_x and max_y    # A structure to hold the queries    class   Query  :   def   __init__  (  self     x1    y1    x2    y2  ):   self  .  x1   =   x1  ;   self  .  y1   =   y1  ;   self  .  x2   =   x2  ;   self  .  y2   =   y2  ;   # A function to update the 2D BIT    def   updateBIT  (  BIT    x    y    val  ):   while   x    <=   N  :   # This loop update all the 1D BIT inside the    # array of 1D BIT = BIT[x]    while   y    <=   N  :   BIT  [  x  ][  y  ]   +=   val  ;   y   +=   (  y   &   -  y  )   x   +=   (  x   &   -  x  )   return  ;   # A function to get sum from (0 0) to (x y)    def   getSum  (  BIT    x    y  ):   sum   =   0  ;   while   x   >   0  :   # This loop sum through all the 1D BIT    # inside the array of 1D BIT = BIT[x]    while   y   >   0  :   sum   +=   BIT  [  x  ][  y  ];   y   -=   y  &-  y   x   -=   x  &-  x   return   sum  ;   # A function to create an auxiliary matrix    # from the given input matrix    def   constructAux  (  mat    aux  ):   # Initialise Auxiliary array to 0    for   i   in   range  (  N   +   1  ):   for   j   in   range  (  N   +   1  ):   aux  [  i  ][  j  ]   =   0   # Construct the Auxiliary Matrix    for   j   in   range  (  1     N   +   1  ):   for   i   in   range  (  1     N   +   1  ):   aux  [  i  ][  j  ]   =   mat  [  N   -   j  ][  i   -   1  ];   return   # A function to construct a 2D BIT    def   construct2DBIT  (  mat    BIT  ):   # Create an auxiliary matrix    aux   =   [  None   for   i   in   range  (  N   +   1  )]   for   i   in   range  (  N   +   1  )   :   aux  [  i  ]  =   [  None   for   i   in   range  (  N   +   1  )]   constructAux  (  mat     aux  )   # Initialise the BIT to 0    for   i   in   range  (  1     N   +   1  ):   for   j   in   range  (  1     N   +   1  ):   BIT  [  i  ][  j  ]   =   0  ;   for   j   in   range  (  1     N   +   1  ):   for   i   in   range  (  1     N   +   1  ):   # Creating a 2D-BIT using update function    # everytime we/ encounter a value in the    # input 2D-array    v1   =   getSum  (  BIT     i     j  );   v2   =   getSum  (  BIT     i     j   -   1  );   v3   =   getSum  (  BIT     i   -   1     j   -   1  );   v4   =   getSum  (  BIT     i   -   1     j  );   # Assigning a value to a particular element    # of 2D BIT    updateBIT  (  BIT     i     j     aux  [  i  ][  j  ]   -   (  v1   -   v2   -   v4   +   v3  ));   return  ;   # A function to answer the queries    def   answerQueries  (  q    m    BIT  ):   for   i   in   range  (  m  ):   x1   =   q  [  i  ]  .  x1   +   1  ;   y1   =   q  [  i  ]  .  y1   +   1  ;   x2   =   q  [  i  ]  .  x2   +   1  ;   y2   =   q  [  i  ]  .  y2   +   1  ;   ans   =   getSum  (  BIT     x2     y2  )   -    getSum  (  BIT     x2     y1   -   1  )   -    getSum  (  BIT     x1   -   1     y2  )   +    getSum  (  BIT     x1   -   1     y1   -   1  );   print  (  'Query ('     q  [  i  ]  .  x1     ' '     q  [  i  ]  .  y1     ' '     q  [  i  ]  .  x2     ' '      q  [  i  ]  .  y2     ') = '     ans     sep   =   ''  )   return  ;   # Driver Code   mat  =   [[  1     2     3     4  ]   [  5     3     8     1  ]   [  4     6     7     5  ]   [  2     4     8     9  ]];   # Create a 2D Binary Indexed Tree    BIT   =   [  None   for   i   in   range  (  N   +   1  )]   for   i   in   range  (  N   +   1  ):   BIT  [  i  ]  =   [  None   for   i   in   range  (  N   +   1  )]   for   j   in   range  (  N   +   1  ):   BIT  [  i  ][  j  ]  =  0   construct2DBIT  (  mat     BIT  );       ''' Queries of the form - x1 y1 x2 y2     For example the query- {1 1 3 2} means the sub-matrix-     y     /     3 | 1 2 3 4 Sub-matrix     2 | 5 3 8 1 {1132} --. 3 8 1     1 | 4 6 7 5 6 7 5     0 | 2 4 8 9     |     --|------ 0 1 2 3 ---. x     |         Hence sum of the sub-matrix = 3+8+1+6+7+5 = 30         '''   q   =   [  Query  (  1     1     3     2  )   Query  (  2     3     3     3  )   Query  (  1     1     1     1  )];   m   =   len  (  q  )   answerQueries  (  q     m     BIT  );   # This code is contributed by phasing17   
C#
   /* C# program to implement 2D Binary Indexed Tree    2D BIT is basically a BIT where each element is another BIT.    Updating by.Adding v on (x y) means it's effect will be found    throughout the rectangle [(x y) (max_x max_y)]    and query for (x y) gives you the result of the rectangle    [(0 0) (x y)] assuming the total rectangle is    [(0 0) (max_x max_y)]. So when you query and update on    this BITyou have to be careful about how many times you are    subtracting a rectangle and.Adding it. Simple set union formula    works here.    So if you want to get the result of a specific rectangle    [(x1 y1) (x2 y2)] the following steps are necessary:    Query(x1y1x2y2) = getSum(x2 y2)-getSum(x2 y1-1) -     getSum(x1-1 y2)+getSum(x1-1 y1-1)    Here 'Query(x1y1x2y2)' means the sum of elements enclosed    in the rectangle with bottom-left corner's co-ordinates    (x1 y1) and top-right corner's co-ordinates - (x2 y2)    Constraints -> x1 <=x2 and y1 <=y2     /    y |     | --------(x2y2)     | | |     | | |     | | |     | ---------     | (x1y1)     |     |___________________________    (0 0) x-->    In this program we have assumed a square matrix. The    program can be easily extended to a rectangular one. */   using     System  ;   class     GFG   {      static     readonly     int     N     =     4  ;     // N-.max_x and max_y    // A structure to hold the queries    public     class     Query      {         public     int     x1       y1  ;     // x and y co-ordinates of bottom left       public     int     x2       y2  ;     // x and y co-ordinates of top right       public     Query  (  int     x1       int     y1       int     x2       int     y2  )      {      this  .  x1     =     x1  ;      this  .  y1     =     y1  ;      this  .  x2     =     x2  ;      this  .  y2     =     y2  ;      }       };      // A function to update the 2D BIT    static     void     updateBIT  (  int     []  BIT       int     x        int     y       int     val  )      {         for     (;     x      <=     N  ;     x     +=     (  x     &     -  x  ))         {         // This loop update all the 1D BIT inside the       // array of 1D BIT = BIT[x]       for     (;     y      <=     N  ;     y     +=     (  y     &     -  y  ))         BIT  [  x    y  ]     +=     val  ;         }         return  ;      }      // A function to get sum from (0 0) to (x y)    static     int     getSum  (  int     []  BIT       int     x       int     y  )      {         int     sum     =     0  ;         for  (;     x     >     0  ;     x     -=     x  &-  x  )         {         // This loop sum through all the 1D BIT       // inside the array of 1D BIT = BIT[x]       for  (;     y     >     0  ;     y     -=     y  &-  y  )         {         sum     +=     BIT  [  x       y  ];         }         }         return     sum  ;      }      // A function to create an auxiliary matrix    // from the given input matrix    static     void     constructAux  (  int     []  mat       int     []  aux  )      {         // Initialise Auxiliary array to 0       for     (  int     i     =     0  ;     i      <=     N  ;     i  ++  )         for     (  int     j     =     0  ;     j      <=     N  ;     j  ++  )         aux  [  i       j  ]     =     0  ;         // Construct the Auxiliary Matrix       for     (  int     j     =     1  ;     j      <=     N  ;     j  ++  )         for     (  int     i     =     1  ;     i      <=     N  ;     i  ++  )         aux  [  i       j  ]     =     mat  [  N     -     j       i     -     1  ];         return  ;      }      // A function to construct a 2D BIT    static     void     construct2DBIT  (  int     []  mat        int     []  BIT  )      {         // Create an auxiliary matrix       int     []  aux     =     new     int  [  N     +     1       N     +     1  ];         constructAux  (  mat       aux  );         // Initialise the BIT to 0       for     (  int     i     =     1  ;     i      <=     N  ;     i  ++  )         for     (  int     j     =     1  ;     j      <=     N  ;     j  ++  )         BIT  [  i       j  ]     =     0  ;         for     (  int     j     =     1  ;     j      <=     N  ;     j  ++  )         {         for     (  int     i     =     1  ;     i      <=     N  ;     i  ++  )         {         // Creating a 2D-BIT using update function       // everytime we/ encounter a value in the       // input 2D-array       int     v1     =     getSum  (  BIT       i       j  );         int     v2     =     getSum  (  BIT       i       j     -     1  );         int     v3     =     getSum  (  BIT       i     -     1       j     -     1  );         int     v4     =     getSum  (  BIT       i     -     1       j  );         // Assigning a value to a particular element       // of 2D BIT       updateBIT  (  BIT       i       j       aux  [  i    j  ]     -         (  v1     -     v2     -     v4     +     v3  ));         }         }         return  ;      }      // A function to answer the queries    static     void     answerQueries  (  Query     []  q       int     m       int     []  BIT  )      {         for     (  int     i     =     0  ;     i      <     m  ;     i  ++  )         {         int     x1     =     q  [  i  ].  x1     +     1  ;         int     y1     =     q  [  i  ].  y1     +     1  ;         int     x2     =     q  [  i  ].  x2     +     1  ;         int     y2     =     q  [  i  ].  y2     +     1  ;         int     ans     =     getSum  (  BIT       x2       y2  )     -      getSum  (  BIT       x2       y1     -     1  )     -         getSum  (  BIT       x1     -     1       y2  )     +      getSum  (  BIT       x1     -     1       y1     -     1  );         Console  .  Write  (  'Query({0} {1} {2} {3}) = {4}n'           q  [  i  ].  x1       q  [  i  ].  y1       q  [  i  ].  x2       q  [  i  ].  y2       ans  );         }         return  ;      }      // Driver Code   public     static     void     Main  (  String  []     args  )      {         int     []  mat     =     {     {  1       2       3       4  }         {  5       3       8       1  }         {  4       6       7       5  }         {  2       4       8       9  }     };         // Create a 2D Binary Indexed Tree       int     []  BIT     =     new     int  [  N     +     1    N     +     1  ];         construct2DBIT  (  mat       BIT  );         /* Queries of the form - x1 y1 x2 y2     For example the query- {1 1 3 2} means the sub-matrix-     y     /     3 | 1 2 3 4 Sub-matrix     2 | 5 3 8 1 {1132} --. 3 8 1     1 | 4 6 7 5 6 7 5     0 | 2 4 8 9     |     --|------ 0 1 2 3 ---. x     |         Hence sum of the sub-matrix = 3+8+1+6+7+5 = 30     */      Query     []  q     =     {  new     Query  (  1       1       3       2  )         new     Query  (  2       3       3       3  )         new     Query  (  1       1       1       1  )};         int     m     =     q  .  Length  ;         answerQueries  (  q       m       BIT  );      }   }   // This code is contributed by Rajput-Ji   
JavaScript
    <  script  >   /* Javascript program to implement 2D Binary Indexed Tree        2D BIT is basically a BIT where each element is another BIT.    Updating by adding v on (x y) means it's effect will be found    throughout the rectangle [(x y) (max_x max_y)]    and query for (x y) gives you the result of the rectangle    [(0 0) (x y)] assuming the total rectangle is    [(0 0) (max_x max_y)]. So when you query and update on    this BITyou have to be careful about how many times you are    subtracting a rectangle and adding it. Simple set union formula    works here.        So if you want to get the result of a specific rectangle    [(x1 y1) (x2 y2)] the following steps are necessary:        Query(x1y1x2y2) = getSum(x2 y2)-getSum(x2 y1-1) -     getSum(x1-1 y2)+getSum(x1-1 y1-1)        Here 'Query(x1y1x2y2)' means the sum of elements enclosed    in the rectangle with bottom-left corner's co-ordinates    (x1 y1) and top-right corner's co-ordinates - (x2 y2)        Constraints -> x1 <=x2 and y1 <=y2         /    y |     | --------(x2y2)     | | |     | | |     | | |     | ---------     | (x1y1)     |     |___________________________    (0 0) x-->        In this program we have assumed a square matrix. The    program can be easily extended to a rectangular one. */   let     N     =     4  ;     // N-.max_x and max_y    // A structure to hold the queries    class     Query      {      constructor  (  x1    y1    x2    y2  )      {      this  .  x1     =     x1  ;      this  .  y1     =     y1  ;      this  .  x2     =     x2  ;      this  .  y2     =     y2  ;      }   }   // A function to update the 2D BIT    function     updateBIT  (  BIT    x    y    val  )   {      for     (;     x      <=     N  ;     x     +=     (  x     &     -  x  ))         {         // This loop update all the 1D BIT inside the       // array of 1D BIT = BIT[x]       for     (;     y      <=     N  ;     y     +=     (  y     &     -  y  ))         BIT  [  x  ][  y  ]     +=     val  ;         }         return  ;      }   // A function to get sum from (0 0) to (x y)    function     getSum  (  BIT    x    y  )   {      let     sum     =     0  ;             for  (;     x     >     0  ;     x     -=     x  &-  x  )         {         // This loop sum through all the 1D BIT       // inside the array of 1D BIT = BIT[x]       for  (;     y     >     0  ;     y     -=     y  &-  y  )         {         sum     +=     BIT  [  x  ][  y  ];         }         }         return     sum  ;      }   // A function to create an auxiliary matrix    // from the given input matrix    function     constructAux  (  mat    aux  )   {      // Initialise Auxiliary array to 0       for     (  let     i     =     0  ;     i      <=     N  ;     i  ++  )         for     (  let     j     =     0  ;     j      <=     N  ;     j  ++  )         aux  [  i  ][  j  ]     =     0  ;             // Construct the Auxiliary Matrix       for     (  let     j     =     1  ;     j      <=     N  ;     j  ++  )         for     (  let     i     =     1  ;     i      <=     N  ;     i  ++  )         aux  [  i  ][  j  ]     =     mat  [  N     -     j  ][  i     -     1  ];             return  ;      }   // A function to construct a 2D BIT    function     construct2DBIT  (  mat    BIT  )   {      // Create an auxiliary matrix       let     aux     =     new     Array  (  N     +     1  );      for  (  let     i  =  0  ;  i   <  (  N  +  1  );  i  ++  )      {      aux  [  i  ]  =  new     Array  (  N  +  1  );      }      constructAux  (  mat       aux  );             // Initialise the BIT to 0       for     (  let     i     =     1  ;     i      <=     N  ;     i  ++  )         for     (  let     j     =     1  ;     j      <=     N  ;     j  ++  )         BIT  [  i  ][  j  ]     =     0  ;             for     (  let     j     =     1  ;     j      <=     N  ;     j  ++  )         {         for     (  let     i     =     1  ;     i      <=     N  ;     i  ++  )         {         // Creating a 2D-BIT using update function       // everytime we/ encounter a value in the       // input 2D-array       let     v1     =     getSum  (  BIT       i       j  );         let     v2     =     getSum  (  BIT       i       j     -     1  );         let     v3     =     getSum  (  BIT       i     -     1       j     -     1  );         let     v4     =     getSum  (  BIT       i     -     1       j  );             // Assigning a value to a particular element       // of 2D BIT       updateBIT  (  BIT       i       j       aux  [  i  ][  j  ]     -         (  v1     -     v2     -     v4     +     v3  ));         }         }         return  ;      }   // A function to answer the queries    function     answerQueries  (  q    m    BIT  )   {      for     (  let     i     =     0  ;     i      <     m  ;     i  ++  )         {         let     x1     =     q  [  i  ].  x1     +     1  ;         let     y1     =     q  [  i  ].  y1     +     1  ;         let     x2     =     q  [  i  ].  x2     +     1  ;         let     y2     =     q  [  i  ].  y2     +     1  ;             let     ans     =     getSum  (  BIT       x2       y2  )     -      getSum  (  BIT       x2       y1     -     1  )     -         getSum  (  BIT       x1     -     1       y2  )     +      getSum  (  BIT       x1     -     1       y1     -     1  );             document  .  write  (  'Query ('  +  q  [  i  ].  x1  +  ' '     +  q  [  i  ].  y1  +  ' '     +  q  [  i  ].  x2  +  ' '     +  q  [  i  ].  y2  +  ') = '     +  ans  +  '  
'
); } return ; } // Driver Code let mat = [[ 1 2 3 4 ] [ 5 3 8 1 ] [ 4 6 7 5 ] [ 2 4 8 9 ]]; // Create a 2D Binary Indexed Tree let BIT = new Array ( N + 1 ); for ( let i = 0 ; i < ( N + 1 ); i ++ ) { BIT [ i ] = new Array ( N + 1 ); for ( let j = 0 ; j < ( N + 1 ); j ++ ) { BIT [ i ][ j ] = 0 ; } } construct2DBIT ( mat BIT ); /* Queries of the form - x1 y1 x2 y2 For example the query- {1 1 3 2} means the sub-matrix- y / 3 | 1 2 3 4 Sub-matrix 2 | 5 3 8 1 {1132} --. 3 8 1 1 | 4 6 7 5 6 7 5 0 | 2 4 8 9 | --|------ 0 1 2 3 ---. x | Hence sum of the sub-matrix = 3+8+1+6+7+5 = 30 */ let q = [ new Query ( 1 1 3 2 ) new Query ( 2 3 3 3 ) new Query ( 1 1 1 1 )]; let m = q . length ; answerQueries ( q m BIT ); // This code is contributed by rag2127 < /script>

Sortir
Query(1 1 3 2) = 30 Query(2 3 3 3) = 7 Query(1 1 1 1) = 6  

Complexité temporelle :  

  • La fonction updateBIT(x y val) et la fonction getSum(x y) prennent du temps O(log(N)*log(M)).
  • Construire le BIT 2D prend O(NM log(N)*log(M)).
  • Puisque dans chacune des requêtes nous appelons la fonction getSum(x y), il faut donc répondre à toutes les requêtes Q O(Q*log(N)*log(M)) temps.
  • Par conséquent, la complexité temporelle globale du programme est O((NM+Q)*log(N)*log(M)) où 
    N = coordonnée X maximale de toute la matrice. 
    M = coordonnée Y maximale de toute la matrice. 
    Q = Nombre de requêtes.

Espace auxiliaire : O(NM) pour stocker le BIT et le tableau auxiliaire


Top Articles

Catégorie

Des Articles Intéressants