所需知识:树状数组
树状数组的表现形式:(不会画图从别的大佬那里摸过来的)
树状数组为分组管理,点与点之间有联系,并非像普通数组一样每个点之间相互独立
树状数组所支持的操作:
修改元素,查询修改后的某个值或者区间的前缀和
树状数组与普通数组的不同:
普通数组 | 树状数组 | |
修改元素 | O(n2) | O(logN) |
求区间和 | O (1) | O(logN) |
因此树状数组比前缀和更适合做要进行多次修改元素的求区间和的操作;
树状数组的三个基本函数:lowbit(i):求某个数的最低一位1表示的数字;
例:lowbit(6)=2;6的二进制表示为110,最后一位1为10,所以表示数字2,lowbit(7)=1,7的二进制表示为111,所以最低位1为1;
add(x,y)将x加上y,且表示的区间和也全随着x的变化而变化;
sum(x)求x之前的区间和,将数组里面所有x前面的数全加起来;
代码具体实现:
int lowbit(int x)
{
return x & -x;
}
void add(int x, int c)
{
for (int i = x; i <= n; i += lowbit(i)) tr[i] += c;
}
int sum(int x)
{
int res = 0;
for (int i = x; i; i -= lowbit(i)) res += tr[i];
return res;
}
题意就是大概把树状数组实现一下,然后跟着题目模拟一遍就行
C++代码:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int n =100000+5;
int tr[n],a[n];
int lowbit(int x)
{
return x & -x;
}
void add(int x, int c)
{
for (int i = x; i <= n; i += lowbit(i)) tr[i] += c;
}
int sum(int x)
{
int res = 0;
for (int i = x; i; i -= lowbit(i)) res += tr[i];
return res;
}
int main()
{
int N,m;
cin>>N>>m;
for (int i = 1; i <= N; i ++ ){
cin>>a[i];
add(i,a[i]);
}
while (m -- ){
int k,a,b;
cin>>k>>a>>b;
if(!k){
cout<<sum(b)-sum(a-1)<<endl;
}
else
add(a,b);
}
return 0;
}