【代码超详解】LOJ #131. 树状数组 2 :区间修改,单点查询

一、题目描述

在这里插入图片描述

样例

样例输入

3 2
1 2 3
1 1 3 0
2 2

样例输出

2

在这里插入图片描述

二、算法分析说明与代码编写指导

如果你尚不了解树状数组,建议先阅读以下题解:
(LOJ 130)
https://blog.csdn.net/COFACTOR/article/details/104199313

通过原数组构造差分数组,然后用这个差分数组建立树状数组,其前 i 项和即为原数组的第 i 项。
原数组的区间修改在差分数组上表现为单点修改,即区间 [L, R] 上的全部数据增加 x 等价于差分数组的第 L 项增加 x,第 R + 1 项减去 x。
模板已经过修改。为了兼容无符号整数,额外提供区间减功能。

Tips:注意差分数组的构造方法。以下提到的方法是错误的:
原来我不知道为什么脑一抽直接在输入数据后将该数据减去差分数组已构造的部分的最后一项,也就是直接写成了 d[i] -= d[i - 1],害得我 WA 了 N 久

三、AC 代码

#include<cstdio>
#pragma warning(disable:4996)
template<class _Ty> class Binary_Index_Tree {
private:
	_Ty* a; size_t n;
	size_t lowbit(const size_t& x) const { return x & (~x + 1); }
public:
	Binary_Index_Tree(const _Ty* arr, const size_t& _Size) {
		a = new _Ty[_Size + 2](), n = _Size;
		for (size_t i = 1, j; i <= n; ++i) {
			a[i] += arr[i], j = i + lowbit(i);
			if (j <= n) a[j] += a[i];
		}
	}
	~Binary_Index_Tree() { delete[] a; }
	void add(size_t pos, const _Ty& val) {
		while (pos <= n) { a[pos] += val, pos += lowbit(pos); }
	}
	_Ty PrefixSum(size_t N) const {
		_Ty sum = 0;
		while (N) { sum += a[N], N -= lowbit(N); }
		return sum;
	}
	_Ty RangeSum(const size_t& L, const size_t& R) const { return PrefixSum(R) - PrefixSum(L - 1); }
	size_t size() const { return n; }
	void subtract(size_t pos, const _Ty& val) {
		while (pos <= n) { a[pos] -= val, pos += lowbit(pos); }
	}
};
unsigned m, q; long long d[1000002], x, y; unsigned long long n, l, r, p;
int main() {
	scanf("%llu%u", &n, &q); ++q;
	for (unsigned i = 1; i <= n; ++i) { scanf("%lld", &y); d[i] = y - x; x = y; }
	static Binary_Index_Tree<long long> b(d, n);
	while (--q) {
		scanf("%u", &m);
		switch (m) {
		case 1:
			scanf("%llu%llu%lld", &l, &r, &x); b.add(l, x); b.subtract(r + 1, x);
			continue;
		default:
			scanf("%llu", &p); printf("%lld\n", b.PrefixSum(p));
		}
	}
	return 0;
}
发布了214 篇原创文章 · 获赞 19 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/COFACTOR/article/details/104206182