所有的整数都可以表示成2的幂和,我们也可以把一串序列表示成一系列子序列的和。采用这个想法,我们可将一个前缀和划分成多个子序列的和,而划分的方法与数的2的幂和具有极其相似的方式。
一方面,子序列的个数是其二进制表示中1的个数,
另一方面,子序列代表的f[i]的个数也是2的幂
常用于区间和查询、单点修改
class NumArray { vector<int> tree; vector<int>& arr; int n; int lowbit(int x) { return x & -x; } //求前缀和 int quary(int x) { int ans = 0; for (int i = x; i > 0; i -= lowbit(i)) { ans += tree[i]; } return ans; } //x位置更新num void add(int x, int num) { for (int i = x; i <= n; i += lowbit(i)) { tree[i] += num; } } public: NumArray(vector<int>& nums) :tree(nums.size() + 1), arr(nums) { n = nums.size(); //初始化树状数组 for (auto i = 0; i < n; i++) { add(i + 1, nums[i]); } } void update(int index, int val) { add(index + 1, val - arr[index]); arr[index] = val; } int sumRange(int left, int right) { return quary(right + 1) - quary(left); } };
时间复杂度 O(logn)
空间复杂度 O(n)