洛谷 P3368——树状数组 / 树状数组模板题,区间修改,单点查询
洛谷 P3368——树状数组
树状数组可以进行单点修改和区间查询,这题要区间修改,要想办法把区间操作变为单点操作,于是想到差分。建树时把原数组的差分数组放入树状数组可以满足我们的要求。而要查询修改后单点 u 的值,可以把差分数组的 1 ~ u 加起来,这个和就是单点 u 的值。而差分数组的 1 ~ u 的和可以分解成 logn 个规模的 tr[] 的和,找到这些 tr[] 相加得到的和即为差分数组 1 ~ u 的和,即为原数组 u 的值。
#include <iostream>
using namespace std;
const int N = 5e5 + 10;
int n, m;
int a[N], tr[N];
int lowbit(int x)
{
return x & -x;
}
void add(int u, int c)
{
for (int i = u; i <= n; i += lowbit(i)) tr[i] += c;
}
int sum(int u)
{
// 差分数组的 1 ~ u 的和可以分解成 logn 个规模的 tr[] 的和,找到这些 tr[] 相加得到的和即为差分数组 1 ~ u 的和,即为原数组 u 的值。
int ans = 0;
for (int i = u; i > 0; i -= lowbit(i)) ans += tr[i];
return ans;
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i ++ )
{
cin >> a[i];
add(i, a[i] - a[i - 1]);
}
while (m -- )
{
int type;
cin >> type;
if (type == 1)
{
int x, y, c;
cin >> x >> y >> c;
add(x, c), add(y + 1, -c);
}else
{
int u;
cin >> u;
cout << sum(u) << '\n';
}
}
return 0;
}