天真的方法是线性迭代范围并乘以范围中的每个数字。
示例:数组:{1,2,3,4,5,6,7,8,9,10}; 将索引3乘以索引8乘以2.假设一个基于索引。
结果数组应为:{1,2,6,8,10,12,14,16,9,10};
我知道Binary索引树可以用于' sum'部分。如何有效地将给定范围与数字相乘?
答案 0 :(得分:1)
如果你想真正修改数组,你不能比天真的线性算法做得更好:你必须迭代整个范围并相应地修改每个索引。
如果你的意思是,你有像你描述的更新操作和查询操作find the sum in the range from x to y
,那么段树可以帮助你这样做。
对于每个更新操作left, right, value
,对于[left, right]
中包含关联范围的每个节点,其总和将乘以value
,因此请相应地更新它并停止继续递归。这也适用于您不会递归的间隔,因此不是实际更新总和,而是在每个节点中存储其相关间隔乘以的数量。
从递归返回时,您可以根据此信息重新计算实际总和。
<强>伪代码强>:
Update(node, left, right, value):
if [left, right] does not intersect node.associated_range:
return
if [left, right] included in node.associated_range:
node.multiplications *= value # 1 initially
return
Update(node.left, left, right, value)
Update(node.right, left, right, value)
node.sum = node.left.sum * node.left.multiplications +
node.right.sum * node.right.multiplications
基本上,每个节点仅通过考虑子段中的乘法来存储其总和。在查询期间,通过使用有关影响该区间的乘法的信息,可以懒惰地计算其真实总和。
然后执行求和查询几乎与段树上的常规查询一样:只需确保将总和乘以它们或父间隔乘以的数量。
<强>伪代码强>:
Query(node, multiplications = 1, left, right):
if [left, right] does not intersect node.associated_range:
return 0
if [left, right] included in node.associated_range:
return node.sum * multiplications
return Query(node.left, multiplications * node.multiplications, left, right) +
Query(node.right, multiplications * node.multiplications, left, right)
最初构建树的函数留作练习(你可以比调用更新n
次更好一些)。
答案 1 :(得分:0)
通过BIT,您还可以更新范围。(Range update by BIT)。
您还可以使用细分树RMQ。您可以轻松地乘以给定的数字。
关于ST和RMQ的精彩教程。 RMQ Topcoder 和Segment Tree
答案 2 :(得分:0)
据我所知,唯一的方法是迭代向量,并应用乘法。
你可以像这样定义一个函数:
void VecMultiply(std::vector<int>& pVector, int Multiplier);
并实现它:
void VecMultiply(std::vector<int>& pVector, int Multiplier)
{
for (unsigned int i = 0; i < pVector.size(); i++)
{
*pVector[i] *= Multiplier;
}
}
或者你甚至可以使用模板传递任何乘以任何东西的向量:
template<typename T>
template<typename M>
void VecMultiply(std::vector<T>& pVector, M Multiplier)
{
for (unsigned int i = 0; i < pVector.size(); i++)
{
*pVector[i] *= Multiplier;
}
}
答案 3 :(得分:0)
您可以遵循线性方法并在C++11
中编码
std::array<int, 10> nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
std::for_each(nums.begin() + 2, nums.begin() + 8, [](int & n) { n *= 2; });
for (int & n : nums) std::cout << n << " ";
<强>输出强>
1 2 6 8 10 12 14 16 9 10