C++ 范围求和查询和使用平方根更新
给定一个数组和几个查询。此外,有两种类型的查询,即update[L,R]表示用它们的平方根更新从L到R的元素,而query[L,R]表示计算从L到R的元素的总和,R.We假设为1基于索引的数组,例如
Input: nums[ ] = { 0, 9, 4, 1, 5, 2, 3 }, Query[ ] = { {1, 1, 3}, {2, 1, 2}, {1, 2, 5}, { 1, 4, 5}} Output: 14 10 7 1st element of 1st query is 1 means we need to calculate range sum from 1 to 3i.e9 + 4 + 1 = 14 1st element of 2nd query is 2 means we need to update range element from 1 to 2 with their square roots now new arr[] array is { 3, 2, 1, 5, 2, 3 } 1st element of 3rd query is 1 means we need to calculate range sum from 2 to 5i.e2 + 1 + 5 + 2 = 10 1st element of the 4th query is 1 means we need to calculate the range sum from 4 to 5i.e5 + 2 = 7 Input: nums[] = { 0, 3, 2, 4, 16, 2 }, Query[ ] = {{1, 1, 3}, {2, 2, 5}} Output: 9
寻找解决方案的方法
简单的方法
我们可以使用循环直到查询结束并返回总和查询的范围总和并更新更新查询的数组。但是这个程序的时间复杂度将是O(q*n)。让我们寻找一种有效的方法。
有效的方法
如果我们减少操作次数或迭代次数,程序可能会更有效率。我们可以使用二叉索引树,在其中我们创建一个数组并使用两个函数进行更新和求和查询。对于更新查询,如果元素为1,则不需要更新它,因为它的平方根仅为1。现在我们可以使用一个集合来存储大于1的索引,并使用二分搜索来查找第L个索引并递增它直到每个范围元素都被更新。然后检查更新的值是否变为1,然后从集合中删除该索引,因为对于任何更新查询,它始终为1。
对于sum查询,我们可以做query(R)-query(L-1)。
示例
上述方法的C++代码
#include <bits/stdc++.h> using namespace std; //输入数组的最大大小可以是 const int m = 200; //创建二叉索引树。 int binary_indexed[m + 1]; //用于更新查询 void update_q(int a, int x, int n){ while(a <= n) { binary_indexed[a] += x; a += a & -a; } } //计算总和范围的函数。 int sum_q(int a){ int s = 0; while(a > 0) { s += binary_indexed[a]; a -= a & -a; } return s; } int main(){ int no_query = 4; int nums[] = { 0, 9, 4, 1, 5, 2, 3 }; int n = sizeof(nums) / sizeof(nums[0]); //用于查询的二维数组。 int q[no_query + 1][3]; q[0][0] = 1, q[0][1] = 1, q[0][2] = 3; q[1][0] = 2, q[1][1] = 1, q[1][2] = 2; q[2][0] = 1, q[2][1] = 2, q[2][2] = 5; q[3][0] = 1, q[3][1] = 4, q[3][2] = 5; set<int> s; for (int i = 1; i < n; i++) { //在大于1的元素集中插入索引。 if (nums[i] > 1) s.insert(i); update_q(i, nums[i], n); } for (int i = 0; i < no_query; i++) { //检查第0个索引以进行更新查询或求和查询。 if (q[i][0] == 2) { while (true) { //使用二分查找查找左索引 auto it = s.lower_bound(q[i][1]); //检查它是否达到正确的索引。 if (it == s.end() || *it > q[i][2]) break; q[i][1] = *it; //将数组元素更新为其平方根。 update_q(*it, (int)sqrt(nums[*it]) - nums[*it], n); nums[*it] = (int)sqrt(nums[*it]); //检查更新的值是否为1将其从集合中删除 if (nums[*it] == 1) s.erase(*it); q[i][1]++; } } else { cout <<"query" << i+1 <<": " << (sum_q(q[i][2]) - sum_q(q[i][1] - 1)) << endl; } } return 0; }输出结果
query1: 14 query3: 10 query4: 7
结论
在本教程中,我们讨论了数组的范围总和查询和范围更新查询。我们讨论了解决这个问题的简单方法和使用二叉索引树的有效方法。我们还讨论了针对这个问题的C++程序,我们可以使用C、Java、Python等编程语言来解决这个问题。我们希望本教程对您有所帮助。