假设我们有一个大小为8的c ++向量,其元素为{0,1,1,0,0,0,1,1},我希望将向量的特定部分的大小增加1,例如,假设需要增加1的向量部分是0到5,那么我们的最终结果是{1,2,2,1,1,0,0,1,1}。
是否可以使用标准的矢量方法(如c中的memset)在恒定时间内完成此操作,而不运行任何循环?
答案 0 :(得分:6)
不......顺便说一下memset
你也没有保证恒定时间操作(在大多数实现中只是非常快但在元素数量上仍然是线性的)。< / p>
如果你需要在一个非常大的向量上进行这种操作(在一个范围内加上/减去一个常量)很多次,你需要获得最终结果然后你可以得到每次更新O(1)使用不同的算法:
这意味着用前一个元素替换每个元素。
// O(n) on the size of the vector, but done only once
for (int n=v.size()-1; i>0; i--) {
v[i] -= v[i-1];
}
使用此表示法向范围添加常量只是意味着将其添加到第一个元素并从结束的元素中减去它。在代码中:
// intervals contains structures with start/stop/value fields
// Operation is O(n) on the **number of intervals**, and does
// not depend on the size of them
for (auto r : intervals) {
v[r.start] += r.value;
v[r.stop+1] -= r.value;
}
最后,您只需要取消初始处理,通过积分返回到每个单元格的正常值。在代码中:
// O(n) on the size of vector, but done only once
for (int i=1,n=v.size(); i<n; i++) {
v[i] += v[i-1];
}
请注意,步骤1和3(推导和集成)都可以在N个内核上并行完成,如果尺寸足够大,效果会很好,即使这样做可能在第一眼看上去并不明显(它不是&至少对我来说是这样的。