树状数组

Posted on 2023-02-14 20:15  lyc2002  阅读(10)  评论(0编辑  收藏  举报

能解决什么问题

动态求连续区间和

对于数组 a[N] 可以求出在 a[i] 左边大于 a[i] 的数的个数,在 a[i] 右边小于 a[i] 的值

时间复杂度

O(log n)

代码

int tr[N];

int lowbit(int x)
{
    return x & -x;
}

void add(int x, int v)
{
    for (int i = x; i < N; i += lowbit(i)) tr[i] += v;
}

void query(int x)
{
    int res = 0;
    for (int i = x; i > 0; i -= lowbit(i)) res += tr[i];
    return res;
}
// 求 a[0, i - 1] 比 a[i] 大的数的个数
for (int i = 0; i < n; i++) {
    sum[i] += query(N - 1) - query(h[i]);
    add(a[i], 1);
}
    
memset(tr, 0, sizeof tr);
    
// 求 a[i + 1, n - 1] 比 a[i] 小的数的个数
for (int i = n - 1; i >= 0; i--) {
    sum[i] += query(a[i] - 1);
    add(a[i], 1);
}