参考链接:https://www.cnblogs.com/Glacier-elk/p/9284523.html
https://blog.csdn.net/qq_40970841/article/details/81297414
如题,已知一个数列,你需要进行下面两种操作(点更新):
1.将某一个数加上x
2.求出某区间每一个数的和
#include<iostream> #define MAXN 2000010 using namespace std; int n,m,a; int q,x,y; int e[MAXN];//树状数组,树状数组index是从1开始的 int lb(int o){ //lowbit return o&(-o); } void addto(int x,int v){ while(x<=n){ e[x]+=v; x+=lb(x); } } int query(int x){ int ans=0;//因为e[i]中有a[i],所以ans从0开始加 while(x>0){ ans+=e[x]; x-=lb(x); } return ans; } int main(){ int i,j; scanf("%d%d",&n,&m); for(i=1;i<=n;i++){ scanf("%d",&a); addto(i,a); //这里与模板2不同,需要先把初值加入树状数组 } for(i=1;i<=m;i++){ scanf("%d%d%d",&q,&x,&y); if(q==1) addto(x,y); else printf("%d ",query(y)-query(x-1)); } return 0; }
如题,已知一个数列,你需要进行下面两种操作(区间更新):
1.将某区间每一个数数加上x
2.求出某一个数的值
#include<iostream> using namespace std; int m,n,x,y,k,q; int a[500010],e[500010];//a[i]是初值,e[i]是累加值(不包含初值) int lb(int o){ //返回o所在区间的长度 return o&(-o); } void addto(int x,int k){ //给树状数组x之前的值+k while(x>0){ e[x]+=k; x-=lb(x); } } int query(int x){ int ans=a[x]; //因为e[i]不包含初值,先把初值加进来 while(x<=n){ ans+=e[x]; x+=lb(x); } return ans; } int main(){ int i,j; scanf("%d%d",&n,&m); for(i=1;i<=n;i++) scanf("%d",&a[i]); for(i=1;i<=m;i++){ scanf("%d",&q); if(q==1){ scanf("%d%d%d",&x,&y,&k); addto(y,k); addto(x-1,-k);//先把y之前的+k,再把x-1之前的-k---->给[x,y]+k } else{ scanf("%d",&x); printf("%d ",query(x)); } } return 0; }