数段数组和线段树


前缀和不支持修改,如果修改后面数据都要重算,最坏o(n)

#include<iostream> using namespace std; const int N=100010; int a[N];int tr[N];int n,m; int lowbit(int x){ return x&-x; } void add(int x,int v){//x位置加上y for(int i=x;i<=n;i+=lowbit(i)) tr[i]+=v; } int query(int x){//求和 int res=0; for(int i=x;i;i-=lowbit(i)) res+=tr[i]; return res; } int main(){ cin>>n>>m; for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) add(i,a[i]); while(m--){ int k,x,y; scanf("%d%d%d",&k,&x,&y); if(k==0) printf("%d\n",query(y)-query(x-1)); else add(x,y); } return 0; }
线段树



#include<iostream> using namespace std; const int N=100010; int a[N]; struct Node{ int l,r; int sum; }st[N*4];//开4倍的是自顶向下,开2倍的是自底向上 int n,m; void pushup(int u){ st[u].sum=st[u<<1].sum+st[u<<1|1].sum; } void build(int u,int l,int r){ if(l==r) st[u]={l,r,a[r]}; else{ st[u]={l,r};//不要忘记 int mid=l+r>>1; build(u<<1,l,mid); build(u<<1|1,mid+1,r); pushup(u); } } int query(int u,int l,int r){ if(st[u].l>=l&&st[u].r<=r) return st[u].sum; int mid=(st[u].l+st[u].r)>>1; int sum=0; if(l<=mid) sum+=query(u<<1,l,r); if(r>mid) sum+=query(u<<1|1,l,r); return sum; } void modify(int u,int x,int v){ if(st[u].l==st[u].r) st[u].sum+=v; else{ int mid=st[u].l+st[u].r>>1; if(x<=mid) modify(u<<1,x,v); else modify(u<<1|1,x,v); pushup(u); } } int main() { cin>>n>>m; for(int i=1;i<=n;i++) scanf("%d",&a[i]); build(1,1,n); while(m--){ int k,x,y; scanf("%d%d%d",&k,&x,&y); if(k==0) cout<<query(1,x,y)<<endl; else modify(1,x,y); } return 0; }

浙公网安备 33010602011771号