树状数组维护前缀和
树状数组是用来维护序列前缀和的数据结构。它的修改与求和都是O(logn)的,效率非常高。
我们设序列为A,则树状数组c中,c[i]记录序列A的区间[ i-lowbit(i)+1 , i ]中所有数的和。 (树状数组是个好东西ovo)
树状数组在进行区间操作时,要从上到下访问,进行单点操作时,要从下到上访问。
树状数组维护序列前缀和的模版如下:
#include <iostream> #include <cstdio> #define maxn 500005 using namespace std; int n,m; int c[maxn];//c[i]存序列a中i-lowbit(i)+1到i的所有数的和(树状数组) int read() { int f=1,x=0; char ch; while(ch<'0'||ch>'9') { if(ch=='-')f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return f*x; } int lowbit(int x) { return x&(-x); } void update(int x,int y) { while(x<=n) { c[x]+=y; x+=lowbit(x); } }//将序列a[x]加上y int sum(int x) { int res=0; while(x>0) { res+=c[x]; x-=lowbit(x); } return res; }//求序列1-x的和 int main() { n=read();m=read(); for(int i=1;i<=n;i++) { //a[i]=read(); int v=read(); update(i,v); } for(int i=1;i<=m;i++) { int op,x,y; op=read();x=read();y=read(); if(op==1) { update(x,y); } if(op==2) { int ans=sum(y)-sum(x-1); printf("%d\n",ans); } } return 0; }