İkili Dizinli Ağaç: Aralık Güncellemesi ve Aralık Sorguları

Bir dizi verildiğinde arr[0..N-1] Aşağıdaki işlemlerin yapılması gerekmektedir. 

  1. güncelleme(l r val) : Dizideki tüm öğelere [l r]'den 'val' ekleyin.
  2. getRangeSum(l r) : Dizideki tüm elemanların toplamını [l r]'den bulun.

Başlangıçta dizideki tüm öğeler 0'dır. Sorgular herhangi bir sırada olabilir, yani aralık toplamından önce birçok güncelleme olabilir.

Örnek:

Giriş: N = 5   // {0 0 0 0 0}
Sorgular: güncelleme: l = 0 r = 4 val = 2
               güncelleme : l = 3 r = 4 val = 3 
               getRangeSum : l = 2 r = 4

Çıkış: [2 4] aralığının elemanlarının toplamı 12'dir
Açıklama: İlk güncellemeden sonra dizi {2 2 2 2 2} olur
İkinci güncellemeden sonra dizi {2 2 2 5 5} olur

Naif Yaklaşım: Sorunu çözmek için aşağıdaki fikri izleyin:

içinde önceki gönderi BIT kullanarak aralık güncelleme ve nokta sorgulama çözümlerini tartıştık. 
rangeUpdate(l r val) : 'l' indeksindeki elemana 'val' ekliyoruz. 'Val'ı 'r+1' indeksindeki elemandan çıkarıyoruz. 
getElement(index) [veya getSum()]: BIT kullanılarak hızlı bir şekilde elde edilebilecek olan 0'dan indekse elemanların toplamını döndürürüz.
rangeSum()'u getSum() sorgularını kullanarak hesaplayabiliriz. 
aralıkSum(l r) = getSum(r) - getSum(l-1)

Basit Bir Çözüm bölümünde tartışılan çözümleri kullanmaktır. önceki gönderi . Aralık güncelleme sorgusu aynıdır. Aralık toplamı sorgusu, aralıktaki tüm öğeler için bir alma sorgusu yapılarak elde edilebilir. 

Verimli Yaklaşım: Sorunu çözmek için aşağıdaki fikri izleyin:

Önek toplamlarını kullanarak aralık toplamını elde ederiz. Güncellemenin önek toplamının hızlı bir şekilde yapılabilmesini sağlayacak şekilde yapıldığından nasıl emin olabiliriz? Önek toplamının [0 k] olduğu bir durumu düşünün (burada 0 <= k < n) is needed after range update on the range [l r]. Three cases arise as k can possibly lie in 3 regions.

  • Durum 1 : 0 < k < l 
    • Güncelleme sorgusu toplam sorgusunu etkilemez.
  • Durum 2 : ben <= k <= r 
    • Bir örnek düşünün:  [2 4] aralığına 2 eklediğinizde elde edilen dizi şöyle olur: 0 0 2 2 2
      Eğer k = 3 ise [0 k] = 4'ün toplamı

Bu sonuç nasıl elde edilir? 
Basitçe l'den val'i ekleyin bu k'ye endeks bu indeks. Güncelleme sorgusundan sonra toplam 'val*(k) - val*(l-1)' artırılır. 

  • Durum 3 : k > r 
    • Bu durumda l'den 'val' eklememiz gerekiyor bu r'ye endeks bu indeks. Bir güncelleme sorgusu nedeniyle toplam 'val*r – val*(l-1)' artırılır.

Gözlemler:  

Durum 1: Toplamın güncellemeden öncekiyle aynı kalması basit.

Durum 2: Toplam, val*k - val*(l-1) kadar artırıldı. 'Val'ı bulabiliriz, bu i'yi bulmaya benzer. bu içindeki eleman aralık güncellemesi ve nokta sorgusu makalesi . Dolayısıyla Aralık Güncellemesi ve Nokta Sorgulamaları için bir BIT tutuyoruz, bu BIT k'deki değeri bulmada yardımcı olacaktır. bu indeks. Şimdi val *k hesaplanırken, ekstra val*(l-1) terimi nasıl ele alınır? 
Bu ekstra terimin üstesinden gelmek için başka bir BIT'i (BIT2) sürdürüyoruz. val * (l-1)'i l'de güncelle o Böylece BIT2'de getSum sorgusu gerçekleştirildiğinde sonuç val*(l-1) olarak verilecektir.

Durum 3: 3. durumda toplam 'val*r - val *(l-1)' artırıldığında bu terimin değeri BIT2 kullanılarak elde edilebilir. Eklemek yerine 'val*(l-1) - val*r' çıkarıyoruz, çünkü bu değeri BIT2'den, durum 2'de yaptığımız gibi val*(l-1) ekleyerek ve her güncelleme işleminde val*r'yi çıkararak elde edebiliriz.

Sorguyu Güncelle 

Güncelleme(BITree1 l val)
Güncelleme(BITree1 r+1 -val)
GüncellemeBIT2(BITree2 l değer*(l-1))
GüncellemeBIT2(BITree2 r+1 -val*r)

Aralık Toplamı 

getSum(BITTree1 k) *k) - getSum(BITTree2 k)

Sorunu çözmek için aşağıdaki adımları izleyin:

  • Verilen buildBITree() fonksiyonunu kullanarak iki ikili indeks ağacını oluşturun
  • Belirli bir aralıktaki Toplamı bulmak için, verilen aralık ve ikili dizinli ağaçlar gibi parametrelerle rangeSum() işlevini çağırın
    • [0 X] aralığında bir toplam döndürecek bir toplam işlevi çağırın
    • Toplamı döndür(R) - toplam(L-1)
      • Bu fonksiyonun içinde, [0 X]'ten dizinin toplamını döndürecek olan getSum() fonksiyonunu çağırın.
      • getSum(Tree1 x) * x - getSum(tree2 x) değerini döndür
      • getSum() işlevinin içinde sıfıra eşit bir tamsayı toplamı oluşturun ve dizini 1 artırın
      • Endeks sıfırdan büyükken toplamı Tree[index] kadar artırın
      • Dizini ağaçtaki üst düğüme taşımak için dizini (index & (-index)) kadar azaltın
      • Toplamı döndür
  • Verilen aralıktaki toplamı yazdır

Yukarıdaki yaklaşımın uygulanması aşağıdadır: 

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>

Çıkış
Sum of elements from [14] is 50 

Zaman Karmaşıklığı : O(q * log(N)) burada q, sorgu sayısıdır.
Yardımcı Alan: AÇIK)