树状数组 差分 区间修改 单点查询 242. 一个简单的整数问题 - AcWing题库
给定长度为 的数列 ,然后输入 行操作指令。
第一类指令形如 C l r d
,表示把数列中第 个数都加 。
第二类指令形如 Q x
,表示询问数列中第 个数的值。
对于每个询问,输出一个整数表示答案。
输入格式
第一行包含两个整数 和 。
第二行包含 个整数 。
接下来 行表示 条指令,每条指令的格式如题目描述所示。
输出格式
对于每个询问,输出一个整数表示答案。
每个答案占一行。
数据范围
,
,
输入样例:
10 5
1 2 3 4 5 6 7 8 9 10
Q 4
Q 1
Q 2
C 1 6 3
Q 2
输出样例:
4
1
2
5
思路
区间修改, 单点查询。
普通的树状数组可以实现单点修改区间查询, 这里需要做一下转化。因为树状数组最后求的是前缀和。 可以先把原数组初始化为差分数组, 即可。
然后求单点的话就是 。
代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
using namespace std;
const int N = 1e5 + 10;
typedef long long LL;
LL t[N];
int n,m;
int lowbit(int x)
{
return x & -x;
}
void add(int u, int x)
{
for(int i = u; i <= n; i+= lowbit(i)) t[i] += x;
}
LL sum(int x)
{
LL res = 0;
for(int i = x; i; i -= lowbit(i)) res += t[i];
return res;
}
int main()
{
cin >> n >> m;
int prev = 0;
for(int i = 1; i <= n; i++)
{
int t;
cin >> t;
add(i, t - prev);
prev = t;
}
while(m--)
{
char s[2];
int l,r,d;
cin >> s >> l;
if(s[0] == 'Q')
cout << sum(l)<< endl;
else {
cin >> r >> d;
add(l, d);
add(r + 1, -d);
}
}
return 0;
}