P3374 【模板】树状数组 1 线段树解题
P3374 【模板】树状数组 1
题解:
线段树的单点更新,区间查询,注意线段树的结点个数是原数组的4倍
#include<iostream> #include<cstdio> using namespace std; long long s[2000100],a[501000],n,m,dx,dy; void btr(int rt,int l,int r)//建树 { if(l==r)//叶结点等于原数组的值 { s[rt]=a[l]; } else { int ls=rt*2,rs=rt*2+1,mid=(l+r)/2;//二分递归求左右子树 btr(ls,l,mid); btr(rs,mid+1,r); s[rt]=s[ls]+s[rs];//回溯求该结点的和 } } void su(int x,int k,int rt,int l,int r)//单点更新 { if(l==r) { s[rt]+=k; return; } int mid=(l+r)/2,ls=rt*2,rs=rt*2+1; if(x>=l&&x<=mid) { su(x,k,ls,l,mid); } else { su(x,k,rs,mid+1,r); } s[rt]+=k; } long long sc(int x,int y,int rt,int l,int r)//区间查询,查询区间[x,y],结点rt,对应区间[l,r] { if(l>=dx&&r<=dy)//查询区间包括结点区间直接返回 { return s[rt]; } long long ans=0; int mid=(l+r)/2,ls=rt*2,rs=rt*2+1; if(y<=mid)//只有左子树 { ans+=sc(x,y,ls,l,mid); } else if(x>mid)//只在右子树 { ans+=sc(x,y,rs,mid+1,r); } else//两个均包括 { ans=ans+sc(x,mid,ls,l,mid)+sc(mid+1,y,rs,mid+1,r); } } int main() { cin>>n>>m; for(int i=1;i<=n;i++) { cin>>a[i]; } btr(1,1,n); for(int i=1;i<=m;i++) { int x,y,c; cin>>c>>x>>y; if(c==1) { su(x,y,1,1,n); } else { dx=x;dy=y; cout<<sc(x,y,1,1,n)<<endl; } } }