Binārais indeksēts koks: diapazona atjaunināšana un diapazona vaicājumi

Dots masīvs arr[0..N-1]. Ir jāveic šādas darbības. 

  1. atjauninājums (l r val) : pievienojiet “val” visiem masīva elementiem no [l r].
  2. iegūtRangeSum(l r) : atrodiet visu masīva elementu summu no [l r].

Sākotnēji visi masīva elementi ir 0. Vaicājumi var būt jebkurā secībā, t.i., pirms diapazona summas var būt daudz atjauninājumu.

Piemērs:

Ievade: N = 5  // {0 0 0 0 0}
Vaicājumi: atjauninājums: l = 0 r = 4 val = 2
               atjauninājums: l = 3 r = 4 val = 3 
               getRangeSum : l = 2 r = 4

Izvade: Diapazona [2 4] elementu summa ir 12
Paskaidrojums: Masīvs pēc pirmā atjaunināšanas kļūst par {2 2 2 2 2}
Masīvs pēc otrā atjaunināšanas kļūst par {2 2 2 5 5}

Naiva pieeja: Lai atrisinātu problēmu, izpildiet šādu ideju:

In iepriekšējā ziņa mēs apspriedām diapazona atjaunināšanu un punktu vaicājumu risinājumus, izmantojot BIT. 
rangeUpdate(l r val) : Mēs pievienojam "val" elementam indeksā "l". Mēs atņemam "val" no elementa indeksā "r+1". 
getElement(index) [vai getSum()]: mēs atgriežam elementu summu no 0 uz indeksu, ko var ātri iegūt, izmantojot BIT.
Mēs varam aprēķināt rangeSum(), izmantojot getSum() vaicājumus. 
rangeSum(l r) = getSum(r) - getSum(l-1)

Vienkāršs risinājums ir izmantot risinājumus, kas apspriesti iepriekšējā ziņa . Diapazona atjaunināšanas vaicājums ir tāds pats. Diapazona summas vaicājumu var sasniegt, veicot iegūšanas vaicājumu visiem diapazona elementiem. 

Efektīva pieeja: Lai atrisinātu problēmu, izpildiet šādu ideju:

Mēs iegūstam diapazona summu, izmantojot prefiksu summas. Kā pārliecināties, ka atjaunināšana tiek veikta tā, lai prefiksu summu varētu veikt ātri? Apsveriet situāciju, kurā prefiksa summa [0 k] (kur 0 <= k < n) is needed after range update on the range [l r]. Three cases arise as k can possibly lie in 3 regions.

  • 1. gadījums : 0 < k < l 
    • Atjaunināšanas vaicājums neietekmēs summas vaicājumu.
  • 2. gadījums : l <= k <= r 
    • Apsveriet piemēru: pievienojiet 2 diapazonam [2 4], rezultāts būtu šāds masīvs: 0 0 2 2 2
      Ja k = 3, summa no [0 k] = 4

Kā iegūt šo rezultātu? 
Vienkārši pievienojiet val no l th indekss uz k th rādītājs. Pēc atjaunināšanas vaicājuma summa tiek palielināta par "val*(k) - val*(l-1)". 

  • 3. gadījums : k > r 
    • Šajā gadījumā mums jāpievieno 'val' no l th indekss uz r th rādītājs. Summa tiek palielināta par 'val*r – val*(l-1)' atjaunināšanas vaicājuma dēļ.

Novērojumi:  

1. gadījums: ir vienkārša, jo summa paliktu tāda pati kā pirms atjaunināšanas.

2. gadījums: Summa tika palielināta par val*k - val*(l-1). Mēs varam atrast “val”, tas ir līdzīgs i atrašanai th elements iekšā diapazona atjauninājumu un punktu vaicājuma rakstu . Tāpēc mēs uzturam vienu BIT diapazona atjaunināšanai un punktu vaicājumiem, šis BIT būs noderīgs, lai atrastu vērtību k th rādītājs. Tagad val * k tiek aprēķināts, kā rīkoties ar papildu terminu val*(l-1)? 
Lai apstrādātu šo papildu termiņu, mēs uzturam vēl vienu BIT (BIT2). Atjaunināt val * (l-1) pie l th indekss, tāpēc, veicot getSum vaicājumu BIT2, rezultāts būs val*(l-1).

3. gadījums: 3. gadījuma summa tika palielināta ar 'val*r - val *(l-1)', šī vārda vērtību var iegūt, izmantojot BIT2. Tā vietā, lai pievienotu, mēs atņemam 'val*(l-1) - val*r', jo mēs varam iegūt šo vērtību no BIT2, pievienojot val*(l-1), kā mēs to darījām 2. gadījumā un atņemot val*r katrā atjaunināšanas darbībā.

Atjaunināt vaicājumu 

Atjauninājums (BITree1 l val)
Atjauninājums (BITree1 r+1 -val)
UpdateBIT2(BITree2 l val*(l-1))
UpdateBIT2 (BITree2 r+1 -val*r)

Diapazona summa 

getSum(BITTree1 k) *k) — getSum(BITTree2 k)

Lai atrisinātu problēmu, veiciet tālāk norādītās darbības.

  • Izveidojiet divus bināro indeksu kokus, izmantojot doto funkciju constructBITree()
  • Lai atrastu summu noteiktā diapazonā, izsauciet funkciju rangeSum() ar parametriem kā norādīto diapazonu un bināri indeksētiem kokiem
    • Izsaukt funkcijas summu, kas atgriezīs summu diapazonā [0 X]
    • Atdeves summa(R) — summa(L-1)
      • Šīs funkcijas ietvaros izsauciet funkciju getSum(), kas atgriezīs masīva summu no [0 X]
      • Atgriezt getSum(Tree1 x) * x - getSum(tree2 x)
      • Funkcijā getSum() izveidojiet veselu skaitļu summu, kas vienāda ar nulli, un palieliniet indeksu par 1
      • Kamēr indekss ir lielāks par nulli, palieliniet summu par Tree[index]
      • Samaziniet indeksu par (index & (-index)), lai pārvietotu indeksu uz koka vecākmezglu
      • Atdeves summa
  • Izdrukājiet summu dotajā diapazonā

Zemāk ir aprakstīta iepriekš minētās pieejas īstenošana: 

C++
   // C++ program to demonstrate Range Update   // and Range Queries using BIT   #include          using     namespace     std  ;   // Returns sum of arr[0..index]. This function assumes   // that the array is preprocessed and partial sums of   // array elements are stored in BITree[]   int     getSum  (  int     BITree  []     int     index  )   {      int     sum     =     0  ;     // Initialize result      // index in BITree[] is 1 more than the index in arr[]      index     =     index     +     1  ;      // Traverse ancestors of BITree[index]      while     (  index     >     0  )     {      // Add current element of BITree to sum      sum     +=     BITree  [  index  ];      // Move index to parent node in getSum View      index     -=     index     &     (  -  index  );      }      return     sum  ;   }   // Updates a node in Binary Index Tree (BITree) at given   // index in BITree. The given value 'val' is added to   // BITree[i] and all of its ancestors in tree.   void     updateBIT  (  int     BITree  []     int     n       int     index       int     val  )   {      // index in BITree[] is 1 more than the index in arr[]      index     =     index     +     1  ;      // Traverse all ancestors and add 'val'      while     (  index      <=     n  )     {      // Add 'val' to current node of BI Tree      BITree  [  index  ]     +=     val  ;      // Update index to that of parent in update View      index     +=     index     &     (  -  index  );      }   }   // Returns the sum of array from [0 x]   int     sum  (  int     x       int     BITTree1  []     int     BITTree2  [])   {      return     (  getSum  (  BITTree1       x  )     *     x  )     -     getSum  (  BITTree2       x  );   }   void     updateRange  (  int     BITTree1  []     int     BITTree2  []     int     n        int     val       int     l       int     r  )   {      // Update Both the Binary Index Trees      // As discussed in the article      // Update BIT1      updateBIT  (  BITTree1       n       l       val  );      updateBIT  (  BITTree1       n       r     +     1       -  val  );      // Update BIT2      updateBIT  (  BITTree2       n       l       val     *     (  l     -     1  ));      updateBIT  (  BITTree2       n       r     +     1       -  val     *     r  );   }   int     rangeSum  (  int     l       int     r       int     BITTree1  []     int     BITTree2  [])   {      // Find sum from [0r] then subtract sum      // from [0l-1] in order to find sum from      // [lr]      return     sum  (  r       BITTree1       BITTree2  )      -     sum  (  l     -     1       BITTree1       BITTree2  );   }   int  *     constructBITree  (  int     n  )   {      // Create and initialize BITree[] as 0      int  *     BITree     =     new     int  [  n     +     1  ];      for     (  int     i     =     1  ;     i      <=     n  ;     i  ++  )      BITree  [  i  ]     =     0  ;      return     BITree  ;   }   // Driver code   int     main  ()   {      int     n     =     5  ;      // Construct two BIT      int     *  BITTree1       *  BITTree2  ;      // BIT1 to get element at any index      // in the array      BITTree1     =     constructBITree  (  n  );      // BIT 2 maintains the extra term      // which needs to be subtracted      BITTree2     =     constructBITree  (  n  );      // Add 5 to all the elements from [04]      int     l     =     0       r     =     4       val     =     5  ;      updateRange  (  BITTree1       BITTree2       n       val       l       r  );      // Add 10 to all the elements from [24]      l     =     2       r     =     4       val     =     10  ;      updateRange  (  BITTree1       BITTree2       n       val       l       r  );      // Find sum of all the elements from      // [14]      l     =     1       r     =     4  ;      cout      < <     'Sum of elements from ['      < <     l      < <     ''      < <     r       < <     '] is '  ;      cout      < <     rangeSum  (  l       r       BITTree1       BITTree2  )      < <     '  n  '  ;      return     0  ;   }   
Java
   // Java program to demonstrate Range Update   // and Range Queries using BIT   import     java.util.*  ;   class   GFG     {      // Returns sum of arr[0..index]. This function assumes      // that the array is preprocessed and partial sums of      // array elements are stored in BITree[]      static     int     getSum  (  int     BITree  []       int     index  )      {      int     sum     =     0  ;     // Initialize result      // index in BITree[] is 1 more than the index in      // arr[]      index     =     index     +     1  ;      // Traverse ancestors of BITree[index]      while     (  index     >     0  )     {      // Add current element of BITree to sum      sum     +=     BITree  [  index  ]  ;      // Move index to parent node in getSum View      index     -=     index     &     (  -  index  );      }      return     sum  ;      }      // Updates a node in Binary Index Tree (BITree) at given      // index in BITree. The given value 'val' is added to      // BITree[i] and all of its ancestors in tree.      static     void     updateBIT  (  int     BITree  []       int     n       int     index        int     val  )      {      // index in BITree[] is 1 more than the index in      // arr[]      index     =     index     +     1  ;      // Traverse all ancestors and add 'val'      while     (  index      <=     n  )     {      // Add 'val' to current node of BI Tree      BITree  [  index  ]     +=     val  ;      // Update index to that of parent in update View      index     +=     index     &     (  -  index  );      }      }      // Returns the sum of array from [0 x]      static     int     sum  (  int     x       int     BITTree1  []       int     BITTree2  []  )      {      return     (  getSum  (  BITTree1       x  )     *     x  )      -     getSum  (  BITTree2       x  );      }      static     void     updateRange  (  int     BITTree1  []       int     BITTree2  []        int     n       int     val       int     l       int     r  )      {      // Update Both the Binary Index Trees      // As discussed in the article      // Update BIT1      updateBIT  (  BITTree1       n       l       val  );      updateBIT  (  BITTree1       n       r     +     1       -  val  );      // Update BIT2      updateBIT  (  BITTree2       n       l       val     *     (  l     -     1  ));      updateBIT  (  BITTree2       n       r     +     1       -  val     *     r  );      }      static     int     rangeSum  (  int     l       int     r       int     BITTree1  []        int     BITTree2  []  )      {      // Find sum from [0r] then subtract sum      // from [0l-1] in order to find sum from      // [lr]      return     sum  (  r       BITTree1       BITTree2  )      -     sum  (  l     -     1       BITTree1       BITTree2  );      }      static     int  []     constructBITree  (  int     n  )      {      // Create and initialize BITree[] as 0      int  []     BITree     =     new     int  [  n     +     1  ]  ;      for     (  int     i     =     1  ;     i      <=     n  ;     i  ++  )      BITree  [  i  ]     =     0  ;      return     BITree  ;      }      // Driver Program to test above function      public     static     void     main  (  String  []     args  )      {      int     n     =     5  ;      // Contwo BIT      int  []     BITTree1  ;      int  []     BITTree2  ;      // BIT1 to get element at any index      // in the array      BITTree1     =     constructBITree  (  n  );      // BIT 2 maintains the extra term      // which needs to be subtracted      BITTree2     =     constructBITree  (  n  );      // Add 5 to all the elements from [04]      int     l     =     0       r     =     4       val     =     5  ;      updateRange  (  BITTree1       BITTree2       n       val       l       r  );      // Add 10 to all the elements from [24]      l     =     2  ;      r     =     4  ;      val     =     10  ;      updateRange  (  BITTree1       BITTree2       n       val       l       r  );      // Find sum of all the elements from      // [14]      l     =     1  ;      r     =     4  ;      System  .  out  .  print  (  'Sum of elements from ['     +     l     +     ''      +     r     +     '] is '  );      System  .  out  .  print  (  rangeSum  (  l       r       BITTree1       BITTree2  )      +     'n'  );      }   }   // This code is contributed by 29AjayKumar   
Python3
   # Python3 program to demonstrate Range Update   # and Range Queries using BIT   # Returns sum of arr[0..index]. This function assumes   # that the array is preprocessed and partial sums of   # array elements are stored in BITree[]   def   getSum  (  BITree  :   list     index  :   int  )   ->   int  :   summ   =   0   # Initialize result   # index in BITree[] is 1 more than the index in arr[]   index   =   index   +   1   # Traverse ancestors of BITree[index]   while   index   >   0  :   # Add current element of BITree to sum   summ   +=   BITree  [  index  ]   # Move index to parent node in getSum View   index   -=   index   &   (  -  index  )   return   summ   # Updates a node in Binary Index Tree (BITree) at given   # index in BITree. The given value 'val' is added to   # BITree[i] and all of its ancestors in tree.   def   updateBit  (  BITTree  :   list     n  :   int     index  :   int     val  :   int  )   ->   None  :   # index in BITree[] is 1 more than the index in arr[]   index   =   index   +   1   # Traverse all ancestors and add 'val'   while   index    <=   n  :   # Add 'val' to current node of BI Tree   BITTree  [  index  ]   +=   val   # Update index to that of parent in update View   index   +=   index   &   (  -  index  )   # Returns the sum of array from [0 x]   def   summation  (  x  :   int     BITTree1  :   list     BITTree2  :   list  )   ->   int  :   return   (  getSum  (  BITTree1     x  )   *   x  )   -   getSum  (  BITTree2     x  )   def   updateRange  (  BITTree1  :   list     BITTree2  :   list     n  :   int     val  :   int     l  :   int     r  :   int  )   ->   None  :   # Update Both the Binary Index Trees   # As discussed in the article   # Update BIT1   updateBit  (  BITTree1     n     l     val  )   updateBit  (  BITTree1     n     r   +   1     -  val  )   # Update BIT2   updateBit  (  BITTree2     n     l     val   *   (  l   -   1  ))   updateBit  (  BITTree2     n     r   +   1     -  val   *   r  )   def   rangeSum  (  l  :   int     r  :   int     BITTree1  :   list     BITTree2  :   list  )   ->   int  :   # Find sum from [0r] then subtract sum   # from [0l-1] in order to find sum from   # [lr]   return   summation  (  r     BITTree1     BITTree2  )   -   summation  (   l   -   1     BITTree1     BITTree2  )   # Driver Code   if   __name__   ==   '__main__'  :   n   =   5   # BIT1 to get element at any index   # in the array   BITTree1   =   [  0  ]   *   (  n   +   1  )   # BIT 2 maintains the extra term   # which needs to be subtracted   BITTree2   =   [  0  ]   *   (  n   +   1  )   # Add 5 to all the elements from [04]   l   =   0   r   =   4   val   =   5   updateRange  (  BITTree1     BITTree2     n     val     l     r  )   # Add 10 to all the elements from [24]   l   =   2   r   =   4   val   =   10   updateRange  (  BITTree1     BITTree2     n     val     l     r  )   # Find sum of all the elements from   # [14]   l   =   1   r   =   4   print  (  'Sum of elements from [  %d    %d  ] is   %d  '   %   (  l     r     rangeSum  (  l     r     BITTree1     BITTree2  )))   # This code is contributed by   # sanjeev2552   
C#
   // C# program to demonstrate Range Update   // and Range Queries using BIT   using     System  ;   class     GFG     {      // Returns sum of arr[0..index]. This function assumes      // that the array is preprocessed and partial sums of      // array elements are stored in BITree[]      static     int     getSum  (  int  []     BITree       int     index  )      {      int     sum     =     0  ;     // Initialize result      // index in BITree[] is 1 more than      // the index in []arr      index     =     index     +     1  ;      // Traverse ancestors of BITree[index]      while     (  index     >     0  )     {      // Add current element of BITree to sum      sum     +=     BITree  [  index  ];      // Move index to parent node in getSum View      index     -=     index     &     (  -  index  );      }      return     sum  ;      }      // Updates a node in Binary Index Tree (BITree) at given      // index in BITree. The given value 'val' is added to      // BITree[i] and all of its ancestors in tree.      static     void     updateBIT  (  int  []     BITree       int     n       int     index        int     val  )      {      // index in BITree[] is 1 more than      // the index in []arr      index     =     index     +     1  ;      // Traverse all ancestors and add 'val'      while     (  index      <=     n  )     {      // Add 'val' to current node of BI Tree      BITree  [  index  ]     +=     val  ;      // Update index to that of      // parent in update View      index     +=     index     &     (  -  index  );      }      }      // Returns the sum of array from [0 x]      static     int     sum  (  int     x       int  []     BITTree1       int  []     BITTree2  )      {      return     (  getSum  (  BITTree1       x  )     *     x  )      -     getSum  (  BITTree2       x  );      }      static     void     updateRange  (  int  []     BITTree1       int  []     BITTree2        int     n       int     val       int     l       int     r  )      {      // Update Both the Binary Index Trees      // As discussed in the article      // Update BIT1      updateBIT  (  BITTree1       n       l       val  );      updateBIT  (  BITTree1       n       r     +     1       -  val  );      // Update BIT2      updateBIT  (  BITTree2       n       l       val     *     (  l     -     1  ));      updateBIT  (  BITTree2       n       r     +     1       -  val     *     r  );      }      static     int     rangeSum  (  int     l       int     r       int  []     BITTree1        int  []     BITTree2  )      {      // Find sum from [0r] then subtract sum      // from [0l-1] in order to find sum from      // [lr]      return     sum  (  r       BITTree1       BITTree2  )      -     sum  (  l     -     1       BITTree1       BITTree2  );      }      static     int  []     constructBITree  (  int     n  )      {      // Create and initialize BITree[] as 0      int  []     BITree     =     new     int  [  n     +     1  ];      for     (  int     i     =     1  ;     i      <=     n  ;     i  ++  )      BITree  [  i  ]     =     0  ;      return     BITree  ;      }      // Driver Code      public     static     void     Main  (  String  []     args  )      {      int     n     =     5  ;      // Contwo BIT      int  []     BITTree1  ;      int  []     BITTree2  ;      // BIT1 to get element at any index      // in the array      BITTree1     =     constructBITree  (  n  );      // BIT 2 maintains the extra term      // which needs to be subtracted      BITTree2     =     constructBITree  (  n  );      // Add 5 to all the elements from [04]      int     l     =     0       r     =     4       val     =     5  ;      updateRange  (  BITTree1       BITTree2       n       val       l       r  );      // Add 10 to all the elements from [24]      l     =     2  ;      r     =     4  ;      val     =     10  ;      updateRange  (  BITTree1       BITTree2       n       val       l       r  );      // Find sum of all the elements from      // [14]      l     =     1  ;      r     =     4  ;      Console  .  Write  (  'Sum of elements from ['     +     l     +     ''     +     r      +     '] is '  );      Console  .  Write  (  rangeSum  (  l       r       BITTree1       BITTree2  )      +     'n'  );      }   }   // This code is contributed by 29AjayKumar   
JavaScript
    <  script  >   // JavaScript program to demonstrate Range Update   // and Range Queries using BIT   // Returns sum of arr[0..index]. This function assumes   // that the array is preprocessed and partial sums of   // array elements are stored in BITree[]   function     getSum  (  BITree    index  )   {      let     sum     =     0  ;     // Initialize result          // index in BITree[] is 1 more than the index in arr[]      index     =     index     +     1  ;          // Traverse ancestors of BITree[index]      while     (  index     >     0  )      {      // Add current element of BITree to sum      sum     +=     BITree  [  index  ];          // Move index to parent node in getSum View      index     -=     index     &     (  -  index  );      }      return     sum  ;   }   // Updates a node in Binary Index Tree (BITree) at given   // index in BITree. The given value 'val' is added to   // BITree[i] and all of its ancestors in tree.   function     updateBIT  (  BITree    n    index    val  )   {      // index in BITree[] is 1 more than the index in arr[]      index     =     index     +     1  ;          // Traverse all ancestors and add 'val'      while     (  index      <=     n  )      {      // Add 'val' to current node of BI Tree      BITree  [  index  ]     +=     val  ;          // Update index to that of parent in update View      index     +=     index     &     (  -  index  );      }   }   // Returns the sum of array from [0 x]   function     sum  (  x    BITTree1    BITTree2  )   {      return     (  getSum  (  BITTree1       x  )     *     x  )     -     getSum  (  BITTree2       x  );   }   function     updateRange  (  BITTree1    BITTree2    n    val    l    r  )   {      // Update Both the Binary Index Trees      // As discussed in the article          // Update BIT1      updateBIT  (  BITTree1       n       l       val  );      updateBIT  (  BITTree1       n       r     +     1       -  val  );          // Update BIT2      updateBIT  (  BITTree2       n       l       val     *     (  l     -     1  ));      updateBIT  (  BITTree2       n       r     +     1       -  val     *     r  );   }   function     rangeSum  (  l    r    BITTree1    BITTree2  )   {      // Find sum from [0r] then subtract sum      // from [0l-1] in order to find sum from      // [lr]      return     sum  (  r       BITTree1       BITTree2  )     -      sum  (  l     -     1       BITTree1       BITTree2  );   }   function     constructBITree  (  n  )   {      // Create and initialize BITree[] as 0      let     BITree     =     new     Array  (  n     +     1  );      for     (  let     i     =     1  ;     i      <=     n  ;     i  ++  )      BITree  [  i  ]     =     0  ;          return     BITree  ;   }   // Driver Program to test above function   let     n     =     5  ;       // Contwo BIT   let     BITTree1  ;   let     BITTree2  ;   // BIT1 to get element at any index   // in the array   BITTree1     =     constructBITree  (  n  );   // BIT 2 maintains the extra term   // which needs to be subtracted   BITTree2     =     constructBITree  (  n  );   // Add 5 to all the elements from [04]   let     l     =     0          r     =     4          val     =     5  ;   updateRange  (  BITTree1       BITTree2       n       val       l       r  );   // Add 10 to all the elements from [24]   l     =     2     ;     r     =     4     ;     val     =     10  ;   updateRange  (  BITTree1       BITTree2       n       val       l       r  );   // Find sum of all the elements from   // [14]   l     =     1     ;     r     =     4  ;   document  .  write  (  'Sum of elements from ['     +     l      +     ''     +     r  +     '] is '  );   document  .  write  (  rangeSum  (  l       r       BITTree1       BITTree2  )  +     '  
'
); // This code is contributed by rag2127 < /script>

Izvade
Sum of elements from [14] is 50 

Laika sarežģītība : O(q * log(N)), kur q ir vaicājumu skaits.
Palīgtelpa: O(N)