一、题目:
如题,已知一个数列,你需要进行下面两种操作:
-
将某一个数加上 �x
-
求出某区间每一个数的和
Input
第一行包含两个正整数 �,�n,m,分别表示该数列数字的个数和操作的总个数。
第二行包含 �n 个用空格分隔的整数,其中第 �i 个数字表示数列第 �i 项的初始值。
接下来 �m 行每行包含 33 个整数,表示一个操作,具体如下:
-
1 x k
含义:将第 �x 个数加上 �k -
2 x y
含义:输出区间 [�,�][x,y] 内每个数的和
Output
输出包含若干行整数,即为所有操作 22 的结果。
Sample 1
Inputcopy | Outputcopy |
---|---|
5 5 1 5 4 2 3 1 1 3 2 2 5 1 3 -1 1 4 2 2 1 4 | 14 16 |
Hint
【数据范围】
对于 30%30% 的数据,1≤�≤81≤n≤8,1≤�≤101≤m≤10;
对于 70%70% 的数据,1≤�,�≤1041≤n,m≤104;
对于 100%100% 的数据,1≤�,�≤5×1051≤n,m≤5×105。
数据保证对于任意时刻,�a 的任意子区间(包括长度为 11 和 �n 的子区间)和均在 [−231,231)[−231,231) 范围内。
样例说明:
故输出结果14、16
前置知识:
二、思路:
树状数组经典的区间查询,单点修改。
若不理解树状数组可看动画加深理解。
三、代码:
#include<iostream>
using namespace std;
const int maxn = 5e5 + 5;
long long b[maxn];
int n, m;
int lowbit(int x) {
return x & (-x);
}
void add(int i,int x) {
while (i <= n) {
b[i] += x;
i += lowbit(i);
}
}
int search(int i) {
int ans = 0;
while (i != 0) {
ans += b[i];
i -= lowbit(i);
}
return ans;
}
int main()
{
cin >> n >> m;
int x;
for (int i = 1; i <= n; i++) {
cin >> x;
add(i, x);
}
int t, y;
while (m--) {
cin >> t >> x >> y;
if (t == 1) {
add(x, y);
}
else {
cout << search(y) - search(x - 1) << endl;
}
}
return 0;
}