【区间处理】——树状数组
【树状数组】重点解决单点,修改区间查询的问题。
学习树状数组最重要的是理解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; }
如果不是很懂运行逻辑的话可以看看示例代码的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; }
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); } };
---------------------------------------------------------------------------------------------
另外,树状数组也有变形,用于解决区间处理的其他问题。
如:区间修改,单点查询【差分的活】
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】

浙公网安备 33010602011771号