洛谷 P3368 【模板】树状数组 2(区间加,单点查询)
题目链接
https://www.luogu.org/problemnew/show/P3368
树状数组
最基础的用法:https://www.cnblogs.com/yinyuqin/p/10961243.html
在这里实现的是区间加,单点查询。
一说到区间加,我们就会想到差分序列,关于差分序列的用法:https://www.cnblogs.com/yinyuqin/p/10961325.html
所以我们在树状数组中维护的不是单点了,而是差分序列。
为什么要用树状数组呢?
因为归根结底,树状数组还是能用O(1)的时间复杂度求出1...n的区间和,因为要求差分序列的前缀和,所以用树状数组来维护。
与最基础的用法唯一的不同之处就是在区间加的时候update两次,修改两个点,和差分序列用法相同。
其他的无异。
代码
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 int n,m,a[500005],d[500005],c[500005]; 5 int lowbit(int x){ 6 return x&(-x); 7 } 8 void update(int x,int v){ 9 for(int i=x;i<=n;i+=lowbit(i)){ 10 c[i]+=v; 11 } 12 } 13 int query(int x){ 14 int res=0; 15 for(int i=x;i>0;i-=lowbit(i)){ 16 res+=c[i]; 17 } 18 return res; 19 } 20 int main() 21 { 22 cin>>n>>m; 23 for(int i=1;i<=n;i++){ 24 scanf("%d",&a[i]); 25 d[i]=a[i]-a[i-1];//差分序列 26 update(i,d[i]); 27 } 28 for(int i=1;i<=m;i++){ 29 int k; 30 cin>>k; 31 if(k==1){ 32 int x,y,v; 33 scanf("%d%d%d",&x,&y,&v); 34 update(x,v);//注意要修改两个点 35 update(y+1,-v); 36 } 37 else{ 38 int x; 39 scanf("%d",&x); 40 cout<<query(x)<<endl; 41 } 42 } 43 return 0; 44 }