芬威克树(BIT)。在O(logN)中找到具有给定累积频率的最小索引

时间:2020-07-15 08:53:29

标签: c++ algorithm binary-search fenwick-tree binary-indexed-tree

假设我有一个带有非负值的BIT(分域树),并且我想在O(logN)中给定的累积频率中找到最小的索引。

现在,我可以这样做O(log ^ 2(N))。

int l = 0, r = n;
while(l < r) {
    int midd = l + (r-l)/2;
    if (get_sum(BIT, midd+1) < given_sum)
        l = midd+1;
    else
        r = midd;
}
return midd + 1;

我知道我们可以如here中所述在O(logN)中找到任何索引或最大索引,因此期望找到具有相同时间复杂度的最低索引。 树的实现方式是一种常见的方式。

vector<int> BIT(n+1);
void update(vector<int> &BIT, int idx, int delta){
    for(int i = idx; i < BIT.size(); i +=(i&-i))
        BIT[i] += delta;
}
int get_sum(vector<int>& BIT, int idx){
    int sum = 0;
    for(int i = idx; i > 0; i-=(i&-i))
        sum += BIT[i];
    return sum;
}

希望能为您提供帮助:)

1 个答案:

答案 0 :(得分:1)

这是我为基于0的索引的Fenwick树实现类似lower_bound的函数的方法:

std::size_t lower_bound(int value) const
{
    std::size_t index = 0;
    for (auto mask = msb_size_mask(); mask != 0; mask >>= 1)
        if (const auto k = mask + index - 1; k < data.size() && data[k] < value)
        {
            value -= data[k];
            index += mask;
        }

    return index;
}

data是基础std::vector<int>。辅助函数msb_size_mask()返回Fenwick树的最小大小,以使底层的二叉树完美,即,如果2^kdata.size()范围内,则返回(2^{k-1}, 2^k]。在C ++ 20中,std::bit_ceil()正是这样做的。

这是更新功能:

void add(std::size_t index, int value)
{
    for (; index < data.size(); index |= index + 1)
        data[index] += value;
}

可以找到完整的代码here