[POJ 2368 A Simple Problem with Integers] 树状数组区间修改、区间查询
知识点:data structure
binary index tree
1. 题目链接
[POJ 2368 A Simple Problem with Integers]
2. 题意描述
对数组
an
进行
q
次区间修改(加上一个数),区间查询。
3. 解题思路
这个用线段树做也就是一个无脑题。之前这类区间查询的还真的很少用树状数组做。
原理:原数组为
ai
,差分数组为
di=ai−ai−1
;则
an=∑ni=1di
;
所以,
∑i=1nai=∑i=1n∑j=1idj=∑i=1n[(n−i+1)∗di]=(x+1)∑i=1ndi−∑i=1n(di∗i)
通过维护差分数组 di ,以及 di∗i 。就可以维护原数组的前缀和。进而维护出原数组的区间和。
4. 实现代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 100000 + 5;
int n, q;
template<class T>
struct BIT {
T C[MAXN];
void I() { memset(C, 0, sizeof(C)); }
inline T lowbit(T x) { return x & (-x); }
void update(int x, LL val) {
while(x < MAXN) { C[x] += val; x += lowbit(x); }
}
T query(int x) {
T ret = 0;
while(x > 0) { ret += C[x]; x -= lowbit(x); }
return ret;
}
};
BIT<LL> a, b;
void update(int x, LL v) { a.update(x, v); b.update(x, v * x); }
void update(int l, int r, LL v) { update(l, v); update(r + 1, -v); }
LL presum(int x) { return (LL)(x + 1) * a.query(x) - b.query(x); }
LL query(int l, int r) { return presum(r) - presum(l - 1); }
int main() {
#ifdef ___LOCAL_WONZY___
freopen("input.txt", "r", stdin);
#endif // ___LOCAL_WONZY___
char op[5];
LL l, r, v;
while(~scanf("%d %d", &n, &q)) {
a.I(); b.I();
vector<LL> A(n + 1);
A[0] = 0;
for(int i = 1; i <= n; i++) {
scanf("%lld", &A[i]);
update(i, A[i] - A[i - 1]); /// 注意这里
}
while(q --) {
scanf("%s %lld %lld", op, &l, &r);
if(op[0] == 'Q') {
printf("%lld\n", query(l, r));
} else {
scanf("%lld", &v);
update(l, r, v);
}
}
}
return 0;
}