【区间处理】——树状数组

XennyYYDS

【树状数组】重点解决单点,修改区间查询的问题。

学习树状数组最重要的是理解x&(-x),树状数组就是x&(-x)的运用。

一份lowbit示例代码:

#include <bits/stdc++.h>
using namespace std;
#define MX 2022
#define IOS ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
#define cn(s) cout << s << endl
typedef long long ll;
int lowbit(int x)
{
    return x & (-x);
}
int main()
{
    IOS;
    int n;
    for (int i = 1; i <= 10; ++i)
    {
        cout << i << "-> :" << endl;
        n = i;
        while (n > 0)
        {
            cout << "  " << n;
            n -= lowbit(n);
        }
        cout << endl;
    }
    // for (int i = 1; i <= 10; ++i)
    // {
    //     cout << i << "-> :" << endl;
    //     n = i;
    //     while (n<=10)
    //     {
    //         n += lowbit(n);
    //         cout << "  " << n;
    //     }
    //     cout << endl;
    // }
    return 0;
}
View Code

 

如果不是很懂运行逻辑的话可以看看示例代码的n值变化。

一份树状数组的示例代码:

 

#define Mx 2022
int a[Mx], c[Mx], n;
//原数组a和树状数组c和数组长度n
//需要注意一点是,树状数组的初始下标为1不是0
int lowbit(int x)
{
    return x & (-x);
}
int updata(int i, int k) //在位置i加上k
{
    while (i <= n)
        c[i] += k, i += lowbit(i);
}
int getsum(int i) //求A[1~i]的和
{
    int sum = 0;
    while (i > 0)
        sum += c[i], i -= lowbit(i);
    return sum;
}
树状数组C模板

 

class NumArray
{
    vector<int> ans;
    int n;
    int lowbit(int x)
    {
        return x & (-x);
    }
    void up(int x, int y)
    {
        while (x <= n)
            ans[x] += y, x += lowbit(x);
    }
    int getsum(int x)
    {
        int sum = 0;
        while (x)
            sum += ans[x], x -= lowbit(x);
        return sum;
    }

public:
    NumArray(vector<int> &nums)
    {
        n = nums.size();
        ans = vector<int>(n + 1);
        for (int i = 0; i < n; ++i)
            up(i + 1, nums[i]);
    }

    int sumRange(int left, int right)
    {
        return getsum(right + 1) - getsum(left);
    }
};
c++模板

 

---------------------------------------------------------------------------------------------

另外,树状数组也有变形,用于解决区间处理的其他问题。

如:区间修改,单点查询【差分的活】

1.需要在最开始建立树状数组的值的时候,

  原本是updata(i,a[i])换为updata(i,a[i]-a[i-1])。

2.然后在修改值的时候,

  如区间[i,j]加上k,只需要updata(i,k)且updata(j+1,-k)即可。

最后查询位置i的值即为getsum(i)

 

未完待续……

【Over】

 

posted @ 2022-03-10 19:32  Renhr  阅读(45)  评论(0)    收藏  举报