给定一个数组arr [0..n-1]。需要执行以下操作。
- update(l,r,val) :将[val]从[l,r]添加到数组中的所有元素。
- getElement(i) :在索引为“ i”的数组中查找元素。
最初,数组中的所有元素均为0。查询可以按任何顺序进行,即,在点查询之前可以进行许多更新。
例子:
Input : arr = {0, 0, 0, 0, 0} Queries: update : l = 0, r = 4, val = 2 getElement : i = 3 update : l = 3, r = 4, val = 3 getElement : i = 3 Output: Element at 3 is 2 Element at 3 is 5 Explanation : Array after first update becomes {2, 2, 2, 2, 2} Array after second update becomes {2, 2, 2, 5, 5}
方法1 [更新:O(n),getElement():O(1)]
- update(l,r,val):从l到r遍历子数组,并将所有元素增加val。
- getElement(i) :要获取第i个索引的元素,只需返回arr [i]。
最坏情况下的时间复杂度为O(q * n),其中q是查询数,n是元素数。
方法2 [更新:O(1),getElement():O(n)]
我们可以避免更新所有元素,并且只能更新数组的2个索引!
- update(l,r,val):在第l个元素中添加“ val”,并从第(r + 1)个元素中减去“ val”,针对所有更新查询执行此操作。
arr[l] = arr[l] + val arr[r+1] = arr[r+1] - val
- getElement(i) :要获取数组中的第i个元素,请找到数组中所有从0到i的整数的和。(前缀和)。
让我们分析一下更新查询。为什么要在第l个索引上添加val?向第l个索引添加val意味着l之后的所有元素都将增加val,因为我们将为每个元素计算前缀和。为什么要从第(r + 1)个索引中减去val?需要从[l,r]进行范围更新,但是我们更新的是[l,n-1],因此我们需要从r之后的所有元素中删除val,即从第(r + 1)个索引中减去val。因此,将val添加到范围[l,r]。下面是上述方法的实现。
C++
// C++ program to demonstrate Range Update // and Point Queries Without using BIT #include
using namespace std; // Updates such that getElement() gets an increased // value when queried from l to r. void update(int arr[], int l, int r, int val) { arr[l] += val; arr[r+1] -= val; } // Get the element indexed at i int getElement(int arr[], int i) { // To get ith element sum of all the elements // from 0 to i need to be computed int res = 0; for (int j = 0 ; j <= i; j++) res += arr[j]; return res; } // Driver program to test above function int main() { int arr[] = {0, 0, 0, 0, 0}; int n = sizeof(arr) / sizeof(arr[0]); int l = 2, r = 4, val = 2; update(arr, l, r, val); //Find the element at Index 4 int index = 4; cout << "Element at index " << index << " is " << getElement(arr, index) << endl; l = 0, r = 3, val = 4; update(arr,l,r,val); //Find the element at Index 3 index = 3; cout << "Element at index " << index << " is " << getElement(arr, index) << endl; return 0; }
Java
// Java program to demonstrate Range Update // and Point Queries Without using BIT class GfG { // Updates such that getElement() gets an increased // value when queried from l to r. static void update(int arr[], int l, int r, int val) { arr[l] += val; if(r + 1 < arr.length) arr[r+1] -= val; } // Get the element indexed at i static int getElement(int arr[], int i) { // To get ith element sum of all the elements // from 0 to i need to be computed int res = 0; for (int j = 0 ; j <= i; j++) res += arr[j]; return res; } // Driver program to test above function public static void main(String[] args) { int arr[] = {0, 0, 0, 0, 0}; int n = arr.length; int l = 2, r = 4, val = 2; update(arr, l, r, val); //Find the element at Index 4 int index = 4; System.out.println("Element at index " + index + " is " +getElement(arr, index)); l = 0; r = 3; val = 4; update(arr,l,r,val); //Find the element at Index 3 index = 3; System.out.println("Element at index " + index + " is " +getElement(arr, index)); } }
Python3
# Python3 program to demonstrate Range # Update and PoQueries Without using BIT # Updates such that getElement() gets an # increased value when queried from l to r. def update(arr, l, r, val): arr[l] += val if r + 1 < len(arr): arr[r + 1] -= val # Get the element indexed at i def getElement(arr, i): # To get ith element sum of all the elements # from 0 to i need to be computed res = 0 for j in range(i + 1): res += arr[j] return res # Driver Code if __name__ == '__main__': arr = [0, 0, 0, 0, 0] n = len(arr) l = 2 r = 4 val = 2 update(arr, l, r, val) # Find the element at Index 4 index = 4 print("Element at index", index, "is", getElement(arr, index)) l = 0 r = 3 val = 4 update(arr, l, r, val) # Find the element at Index 3 index = 3 print("Element at index", index, "is", getElement(arr, index)) # This code is contributed by PranchalK
C#
// C# program to demonstrate Range Update // and Point Queries Without using BIT using System; class GfG { // Updates such that getElement() // gets an increased value when // queried from l to r. static void update(int []arr, int l, int r, int val) { arr[l] += val; if(r + 1 < arr.Length) arr[r + 1] -= val; } // Get the element indexed at i static int getElement(int []arr, int i) { // To get ith element sum of all the elements // from 0 to i need to be computed int res = 0; for (int j = 0 ; j <= i; j++) res += arr[j]; return res; } // Driver code public static void Main(String[] args) { int []arr = {0, 0, 0, 0, 0}; int n = arr.Length; int l = 2, r = 4, val = 2; update(arr, l, r, val); //Find the element at Index 4 int index = 4; Console.WriteLine("Element at index " + index + " is " + getElement(arr, index)); l = 0; r = 3; val = 4; update(arr,l,r,val); //Find the element at Index 3 index = 3; Console.WriteLine("Element at index " + index + " is " + getElement(arr, index)); } } // This code is contributed by PrinciRaj1992
PHP
C++
// C++ code to demonstrate Range Update and // Point Queries on a Binary Index Tree #include
using namespace std; // 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); } } // Constructs and returns a Binary Indexed Tree for given // array of size n. int *constructBITree(int arr[], int n) { // Create and initialize BITree[] as 0 int *BITree = new int[n+1]; for (int i=1; i<=n; i++) BITree[i] = 0; // Store the actual values in BITree[] using update() for (int i=0; i 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 such that getElement() gets an increased // value when queried from l to r. void update(int BITree[], int l, int r, int n, int val) { // Increase value at 'l' by 'val' updateBIT(BITree, n, l, val); // Decrease value at 'r+1' by 'val' updateBIT(BITree, n, r+1, -val); } // Driver program to test above function int main() { int arr[] = {0, 0, 0, 0, 0}; int n = sizeof(arr)/sizeof(arr[0]); int *BITree = constructBITree(arr, n); // Add 2 to all the element from [2,4] int l = 2, r = 4, val = 2; update(BITree, l, r, n, val); // Find the element at Index 4 int index = 4; cout << "Element at index " << index << " is " << getSum(BITree,index) << "\n"; // Add 2 to all the element from [0,3] l = 0, r = 3, val = 4; update(BITree, l, r, n, val); // Find the element at Index 3 index = 3; cout << "Element at index " << index << " is " << getSum(BITree,index) << "\n" ; return 0; }
Java
/* Java code to demonstrate Range Update and * Point Queries on a Binary Index Tree. * This method only works when all array * values are initially 0.*/ class GFG { // Max tree size final static int MAX = 1000; static int BITree[] = new int[MAX]; // 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. public static void updateBIT(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 BITree BITree[index] += val; // Update index to that // of parent in update View index += index & (-index); } } // Constructs Binary Indexed Tree // for given array of size n. public static void constructBITree(int arr[], int n) { // Initialize BITree[] as 0 for(int i = 1; i <= n; i++) BITree[i] = 0; // Store the actual values // in BITree[] using update() for(int i = 0; i < n; i++) updateBIT(n, i, arr[i]); // Uncomment below lines to // see contents of BITree[] // for (int i=1; i<=n; i++) // cout << BITree[i] << " "; } // SERVES THE PURPOSE OF getElement() // Returns sum of arr[0..index]. This // function assumes that the array is // preprocessed and partial sums of // array elements are stored in BITree[] public static int getSum(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 the sum return sum; } // Updates such that getElement() // gets an increased value when // queried from l to r. public static void update(int l, int r, int n, int val) { // Increase value at // 'l' by 'val' updateBIT(n, l, val); // Decrease value at // 'r+1' by 'val' updateBIT(n, r + 1, -val); } // Driver Code public static void main(String args[]) { int arr[] = {0, 0, 0, 0, 0}; int n = arr.length; constructBITree(arr,n); // Add 2 to all the // element from [2,4] int l = 2, r = 4, val = 2; update(l, r, n, val); int index = 4; System.out.println("Element at index "+ index + " is "+ getSum(index)); // Add 2 to all the // element from [0,3] l = 0; r = 3; val = 4; update(l, r, n, val); // Find the element // at Index 3 index = 3; System.out.println("Element at index "+ index + " is "+ getSum(index)); } } // This code is contributed // by Puneet Kumar.
Python3
# Python3 code to demonstrate Range Update and # PoQueries on a Binary Index Tree # 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(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) # Constructs and returns a Binary Indexed Tree for given # array of size n. def constructBITree(arr, n): # Create and initialize BITree[] as 0 BITree = [0]*(n+1) # Store the actual values in BITree[] using update() for i in range(n): updateBIT(BITree, n, i, arr[i]) return BITree # SERVES THE PURPOSE OF getElement() # 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, index): sum = 0 # Iniialize 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 such that getElement() gets an increased # value when queried from l to r. def update(BITree, l, r, n, val): # Increase value at 'l' by 'val' updateBIT(BITree, n, l, val) # Decrease value at 'r+1' by 'val' updateBIT(BITree, n, r+1, -val) # Driver code arr = [0, 0, 0, 0, 0] n = len(arr) BITree = constructBITree(arr, n) # Add 2 to all the element from [2,4] l = 2 r = 4 val = 2 update(BITree, l, r, n, val) # Find the element at Index 4 index = 4 print("Element at index", index, "is", getSum(BITree, index)) # Add 2 to all the element from [0,3] l = 0 r = 3 val = 4 update(BITree, l, r, n, val) # Find the element at Index 3 index = 3 print("Element at index", index, "is", getSum(BITree,index)) # This code is contributed by mohit kumar 29
C#
using System; /* C# code to demonstrate Range Update and * Point Queries on a Binary Index Tree. * This method only works when all array * values are initially 0.*/ public class GFG { // Max tree size public const int MAX = 1000; public static int[] BITree = new int[MAX]; // 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. public static void updateBIT(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 BITree BITree[index] += val; // Update index to that // of parent in update View index += index & (-index); } } // Constructs Binary Indexed Tree // for given array of size n. public static void constructBITree(int[] arr, int n) { // Initialize BITree[] as 0 for (int i = 1; i <= n; i++) { BITree[i] = 0; } // Store the actual values // in BITree[] using update() for (int i = 0; i < n; i++) { updateBIT(n, i, arr[i]); } // Uncomment below lines to // see contents of BITree[] // for (int i=1; i<=n; i++) // cout << BITree[i] << " "; } // SERVES THE PURPOSE OF getElement() // Returns sum of arr[0..index]. This // function assumes that the array is // preprocessed and partial sums of // array elements are stored in BITree[] public static int getSum(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 the sum return sum; } // Updates such that getElement() // gets an increased value when // queried from l to r. public static void update(int l, int r, int n, int val) { // Increase value at // 'l' by 'val' updateBIT(n, l, val); // Decrease value at // 'r+1' by 'val' updateBIT(n, r + 1, -val); } // Driver Code public static void Main(string[] args) { int[] arr = new int[] {0, 0, 0, 0, 0}; int n = arr.Length; constructBITree(arr,n); // Add 2 to all the // element from [2,4] int l = 2, r = 4, val = 2; update(l, r, n, val); int index = 4; Console.WriteLine("Element at index " + index + " is " + getSum(index)); // Add 2 to all the // element from [0,3] l = 0; r = 3; val = 4; update(l, r, n, val); // Find the element // at Index 3 index = 3; Console.WriteLine("Element at index " + index + " is " + getSum(index)); } } // This code is contributed by Shrikant13
输出:
Element at index 4 is 2 Element at index 3 is 6
时间复杂度:O(q * n),其中q是查询数。
方法3(使用二进制索引树)
在方法2中,我们已经看到该问题可以简化为更新和前缀和查询。我们已经看到,BIT可用于在O(Logn)时间内进行更新和前缀和查询。
下面是实现。
C++
// C++ code to demonstrate Range Update and // Point Queries on a Binary Index Tree #include
using namespace std; // 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); } } // Constructs and returns a Binary Indexed Tree for given // array of size n. int *constructBITree(int arr[], int n) { // Create and initialize BITree[] as 0 int *BITree = new int[n+1]; for (int i=1; i<=n; i++) BITree[i] = 0; // Store the actual values in BITree[] using update() for (int i=0; i 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 such that getElement() gets an increased // value when queried from l to r. void update(int BITree[], int l, int r, int n, int val) { // Increase value at 'l' by 'val' updateBIT(BITree, n, l, val); // Decrease value at 'r+1' by 'val' updateBIT(BITree, n, r+1, -val); } // Driver program to test above function int main() { int arr[] = {0, 0, 0, 0, 0}; int n = sizeof(arr)/sizeof(arr[0]); int *BITree = constructBITree(arr, n); // Add 2 to all the element from [2,4] int l = 2, r = 4, val = 2; update(BITree, l, r, n, val); // Find the element at Index 4 int index = 4; cout << "Element at index " << index << " is " << getSum(BITree,index) << "\n"; // Add 2 to all the element from [0,3] l = 0, r = 3, val = 4; update(BITree, l, r, n, val); // Find the element at Index 3 index = 3; cout << "Element at index " << index << " is " << getSum(BITree,index) << "\n" ; return 0; } Java
/* Java code to demonstrate Range Update and * Point Queries on a Binary Index Tree. * This method only works when all array * values are initially 0.*/ class GFG { // Max tree size final static int MAX = 1000; static int BITree[] = new int[MAX]; // 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. public static void updateBIT(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 BITree BITree[index] += val; // Update index to that // of parent in update View index += index & (-index); } } // Constructs Binary Indexed Tree // for given array of size n. public static void constructBITree(int arr[], int n) { // Initialize BITree[] as 0 for(int i = 1; i <= n; i++) BITree[i] = 0; // Store the actual values // in BITree[] using update() for(int i = 0; i < n; i++) updateBIT(n, i, arr[i]); // Uncomment below lines to // see contents of BITree[] // for (int i=1; i<=n; i++) // cout << BITree[i] << " "; } // SERVES THE PURPOSE OF getElement() // Returns sum of arr[0..index]. This // function assumes that the array is // preprocessed and partial sums of // array elements are stored in BITree[] public static int getSum(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 the sum return sum; } // Updates such that getElement() // gets an increased value when // queried from l to r. public static void update(int l, int r, int n, int val) { // Increase value at // 'l' by 'val' updateBIT(n, l, val); // Decrease value at // 'r+1' by 'val' updateBIT(n, r + 1, -val); } // Driver Code public static void main(String args[]) { int arr[] = {0, 0, 0, 0, 0}; int n = arr.length; constructBITree(arr,n); // Add 2 to all the // element from [2,4] int l = 2, r = 4, val = 2; update(l, r, n, val); int index = 4; System.out.println("Element at index "+ index + " is "+ getSum(index)); // Add 2 to all the // element from [0,3] l = 0; r = 3; val = 4; update(l, r, n, val); // Find the element // at Index 3 index = 3; System.out.println("Element at index "+ index + " is "+ getSum(index)); } } // This code is contributed // by Puneet Kumar.
Python3
# Python3 code to demonstrate Range Update and # PoQueries on a Binary Index Tree # 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(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) # Constructs and returns a Binary Indexed Tree for given # array of size n. def constructBITree(arr, n): # Create and initialize BITree[] as 0 BITree = [0]*(n+1) # Store the actual values in BITree[] using update() for i in range(n): updateBIT(BITree, n, i, arr[i]) return BITree # SERVES THE PURPOSE OF getElement() # 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, index): sum = 0 # Iniialize 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 such that getElement() gets an increased # value when queried from l to r. def update(BITree, l, r, n, val): # Increase value at 'l' by 'val' updateBIT(BITree, n, l, val) # Decrease value at 'r+1' by 'val' updateBIT(BITree, n, r+1, -val) # Driver code arr = [0, 0, 0, 0, 0] n = len(arr) BITree = constructBITree(arr, n) # Add 2 to all the element from [2,4] l = 2 r = 4 val = 2 update(BITree, l, r, n, val) # Find the element at Index 4 index = 4 print("Element at index", index, "is", getSum(BITree, index)) # Add 2 to all the element from [0,3] l = 0 r = 3 val = 4 update(BITree, l, r, n, val) # Find the element at Index 3 index = 3 print("Element at index", index, "is", getSum(BITree,index)) # This code is contributed by mohit kumar 29
C#
using System; /* C# code to demonstrate Range Update and * Point Queries on a Binary Index Tree. * This method only works when all array * values are initially 0.*/ public class GFG { // Max tree size public const int MAX = 1000; public static int[] BITree = new int[MAX]; // 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. public static void updateBIT(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 BITree BITree[index] += val; // Update index to that // of parent in update View index += index & (-index); } } // Constructs Binary Indexed Tree // for given array of size n. public static void constructBITree(int[] arr, int n) { // Initialize BITree[] as 0 for (int i = 1; i <= n; i++) { BITree[i] = 0; } // Store the actual values // in BITree[] using update() for (int i = 0; i < n; i++) { updateBIT(n, i, arr[i]); } // Uncomment below lines to // see contents of BITree[] // for (int i=1; i<=n; i++) // cout << BITree[i] << " "; } // SERVES THE PURPOSE OF getElement() // Returns sum of arr[0..index]. This // function assumes that the array is // preprocessed and partial sums of // array elements are stored in BITree[] public static int getSum(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 the sum return sum; } // Updates such that getElement() // gets an increased value when // queried from l to r. public static void update(int l, int r, int n, int val) { // Increase value at // 'l' by 'val' updateBIT(n, l, val); // Decrease value at // 'r+1' by 'val' updateBIT(n, r + 1, -val); } // Driver Code public static void Main(string[] args) { int[] arr = new int[] {0, 0, 0, 0, 0}; int n = arr.Length; constructBITree(arr,n); // Add 2 to all the // element from [2,4] int l = 2, r = 4, val = 2; update(l, r, n, val); int index = 4; Console.WriteLine("Element at index " + index + " is " + getSum(index)); // Add 2 to all the // element from [0,3] l = 0; r = 3; val = 4; update(l, r, n, val); // Find the element // at Index 3 index = 3; Console.WriteLine("Element at index " + index + " is " + getSum(index)); } } // This code is contributed by Shrikant13
输出:
Element at index 4 is 2 Element at index 3 is 6
时间复杂度: O(q * log n)+ O(n * log n)其中q是查询数。
当大多数查询是getElement()时,方法1是有效的;当大多数查询是updates()时,方法2是有效的;当两个查询混合使用时,方法3是首选的。