问题:
我偶然发现了Fenwick树(二叉索引树),它们可以轻松地计算累积总和。但是,我仅发现实现中,leeves(求和数)的数量是恒定的(但是它们的值可以改变)。 是否有像通用的Fenwick树之类的东西,它允许改变后备身材的数量(即需求量),即具有可变的大小?
背景
我目前正在编写一些随机模拟代码(在C++中):中有多个球,每个球i都有一定的概率p_i被绘制。在绘制事件中,一个球被绘制(并移除),并被两个具有新概率的新球替换(并且所有概率都被相应地缩放;我已经高效地执行了“缩放”,因此不必理会)。在某个时候,我开始移除球,以使球的数量围绕恒定值波动(之前知道)。为了有效地进行绘图,我想使用二叉树。标准的Fenwick树完全符合我的要求,只是它不允许更改骨灰盒中球的数量。
典型数字
从10个球开始,添加球,一旦大约1000个球就开始移除球,这样骨灰盒中就会有900到1100个球(即添加和移除球,使得数量保持在1000个左右)。
到目前为止的解决方法
估计所需的最大球数(有一定的安全余量,例如1200个球),并使恒定大小的Fenwick树变大,其中大多数球最初被绘制为0并被连续更新的概率。
非常感谢您的帮助!
马蒂亚斯
最佳答案
实际上,普通(不以任何方式概括)的Fenwick树允许随时增加叶子数量。
一些特定的实现可能不允许这样做。但这可能是固定的。例如,implementation from TopCoder不允许更改叶子数。问题在于update
函数会修改从给定索引开始并向上的数组元素,并在达到某个限制(MaxVal
)时停止,这在我们的情况下是事先未知的。 read
函数迭代向下的数组元素,因此不需要知道当前的数组大小。如果我们在update
和read
之间交换数组迭代代码,则可以解决此问题:现在update
不需要知道MaxVal
,MaxVal
中使用了read
,并且可以使用MaxVal
来使用最大的更新索引。
int read(int idx){
int sum = 0;
while (idx <= MaxVal){
sum += tree[idx];
idx += (idx & -idx);
}
return sum;
}
void update(int idx ,int val){
while (idx > 0){
tree[idx] += val;
idx -= (idx & -idx);
}
}
笔记。
read
返回前缀和)不同,此实现提供后缀和。如果需要前缀总和,只需从总值中减去read
返回的值即可。 BLSR
。 关于c++ - 动态(即大小可变)的Fenwick树?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21995930/