Даден е масив arr[0..N-1]. Трябва да се извършат следните операции.
- актуализация (l r стойност) : Добавете „val“ към всички елементи в масива от [l r].
- getRangeSum(l r) : Намерете сумата от всички елементи в масива от [l r].
Първоначално всички елементи в масива са 0. Заявките могат да бъдат в произволен ред, т.е. може да има много актуализации преди сумата на диапазона.
Пример:
вход: N = 5 // {0 0 0 0 0}
Запитвания: актуализация: l = 0 r = 4 стойност = 2
актуализация: l = 3 r = 4 стойност = 3
getRangeSum: l = 2 r = 4Изход: Сумата от елементите на обхват [2 4] е 12
Обяснение: Масивът след първата актуализация става {2 2 2 2 2}
Масивът след втората актуализация става {2 2 2 5 5}
Наивен подход: За да разрешите проблема, следвайте идеята по-долу:
В предишен пост обсъдихме актуализацията на обхвата и решенията за заявка на точки с помощта на BIT.
rangeUpdate(l r val) : Добавяме 'val' към елемента с индекс 'l'. Изваждаме 'val' от елемента с индекс 'r+1'.
getElement(index) [или getSum()]: Връщаме сума от елементи от 0 до индекс, която може бързо да бъде получена с помощта на BIT.
Можем да изчислим rangeSum() с помощта на getSum() заявки.
rangeSum(l r) = getSum(r) - getSum(l-1)маса за реагиранеПросто решение е да използвате решенията, обсъдени в предишен пост . Заявката за актуализиране на диапазона е същата. Заявка за сума на диапазон може да бъде постигната чрез извършване на заявка за получаване за всички елементи в диапазона.
Ефикасен подход: За да разрешите проблема, следвайте идеята по-долу:
Получаваме сума на диапазона, като използваме префиксни суми. Как да се уверите, че актуализацията е направена по начин, така че сумата на префикса да може да се извърши бързо? Помислете за ситуация, при която префикс sum [0 k] (където 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 : 0< k < l
- Заявката за актуализиране няма да повлияе на заявката за сума.
- Случай 2 : л<= k <= r
- Помислете за пример: Добавете 2 към диапазон [2 4], резултатният масив ще бъде: 0 0 2 2 2
Ако k = 3 Сумата от [0 k] = 4Как да получите този резултат?
Просто добавете стойността от lthиндекс към kthиндекс. Сумата се увеличава с 'val*(k) - val*(l-1)' след заявката за актуализиране.
- Случай 3 : k > r
- За този случай трябва да добавим 'val' от lthиндекс към rthиндекс. Сумата се увеличава с „val*r – val*(l-1)“ поради заявка за актуализиране.
Наблюдения:
Случай 1: е проста, тъй като сумата ще остане същата, както беше преди актуализацията.
Случай 2: Сумата беше увеличена с val*k - val*(l-1). Можем да намерим „val“, това е подобно на намирането на ithелемент в актуализация на диапазона и статия за заявка на точки . Така че поддържаме един BIT за обновяване на обхвата и заявки за точки, този BIT ще бъде полезен при намиране на стойността при kthиндекс. Сега val * k се изчислява как да се справи с допълнителния термин val*(l-1)?
За да се справим с този допълнителен срок, ние поддържаме друг BIT (BIT2). Актуализиране на стойност * (l-1) при lthиндекс, така че когато заявката getSum се изпълни на BIT2, ще даде резултат като val*(l-1).
Случай 3: Сумата в случай 3 беше увеличена с 'val*r - val *(l-1)' стойността на този член може да бъде получена с помощта на BIT2. Вместо да добавяме, ние изваждаме 'val*(l-1) - val*r', тъй като можем да получим тази стойност от BIT2 чрез добавяне на val*(l-1), както направихме в случай 2 и изваждане на val*r при всяка операция за актуализиране.
Заявка за актуализиране
Актуализация (BITree1 l стойност)
Актуализация (BITree1 r+1 -val)
UpdateBIT2(BITree2 l val*(l-1))
UpdateBIT2(BITree2 r+1 -val*r)Обхват Сума
getSum(BITTree1 k) *k) - getSum(BITTree2 k)
инсталирайте maven
Следвайте стъпките по-долу, за да разрешите проблема:
- Създайте двете двоични индексни дървета, като използвате дадената функция constructBITree()
- За да намерите сумата в даден диапазон, извикайте функцията rangeSum() с параметри като дадения диапазон и двоично индексирани дървета
- Извикайте функция сума, която ще върне сума в диапазона [0 X]
- Върнете сума(R) - сума(L-1)
- Вътре в тази функция извикайте функцията getSum(), която ще върне сумата на масива от [0 X]
- Връща getSum(Tree1 x) * x - getSum(tree2 x)
- Във функцията getSum() създайте цяло число, равно на нула, и увеличете индекса с 1
- Докато индексът е по-голям от нула, увеличете сумата с Tree[index]
- Намалете индекса с (index & (-index)), за да преместите индекса към родителския възел в дървото
- Сума за връщане
- Отпечатайте сумата в дадения диапазон
По-долу е изпълнението на горния подход:
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(BITreeindex) { 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(BITreenindexval) { // 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(xBITTree1BITTree2) { return (getSum(BITTree1 x) * x) - getSum(BITTree2 x); } function updateRange(BITTree1BITTree2nvallr) { // 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(lrBITTree1BITTree2) { // 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>
Изход
Sum of elements from [14] is 50
Времева сложност : O(q * log(N)), където q е броят на заявките.
Помощно пространство: O(N)