目录
题目-一个简单的整数问题

问题分析
区间修改, 单点查询
但是树状数组只能支持单点修改, 单点查询
因此可以求出原序列的差分序列 , 假设原序列是 a 1 , a 2 , a 3 , . . . , a n a_1, a_2, a_3, ..., a_n a1,a2,a3,...,an
求出差分序列
b 1 , b 2 , b 3 , . . . , b n b_1, b_2, b_3, ..., b_n b1,b2,b3,...,bn
b 1 = a 1 − a 0 b_1 = a_1 - a_0 b1=a1−a0, b 2 = a 2 − a 1 b_2 = a_2 - a_1 b2=a2−a1...
差分序列的前缀和 就是原来位置的值
如果对原序列的一个区间 [ L , R ] [L, R] [L,R]进行增加 d d d, 那么就是差分序列 b L + d b_{L} + d bL+d, b R + 1 − d b_{R+ 1} - d bR+1−d
算法步骤
- 求出原序列的差分序列
- 构建树状数组
- 区间修改转化为差分序列的单点修改
- 查询原序列的 x x x位置的值, 相当于求差分序列的前缀和, 也就是树状数组的操作
算法时间复杂度 O ( M log N ) O(M \log N) O(MlogN)
代码实现
cpp
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n, m;
int a[N], b[N];
int tr[N];
int lowbit(int x) {
return x & -x;
}
void modify(int u, int val) {
for (int i = u; i <= n; i += lowbit(i)) tr[i] += val;
}
int get(int u) {
int ans = 0;
for (int i = u; i; i -= lowbit(i)) ans += tr[i];
return ans;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
b[i] = a[i] - a[i - 1];
}
for (int i = 1; i <= n; ++i) modify(i, b[i]);
while (m--) {
char c;
cin >> c;
if (c == 'C') {
int l, r, val;
cin >> l >> r >> val;
modify(l, val);
modify(r + 1, -val);
}
else {
int x;
cin >> x;
cout << get(x) << '\n';
}
}
return 0;
}