树状数组(区间修改,单点求值)
1 const int N=500005; 2 int a[N],c[N],n,m; 3 4 void modify(int x,int y) 5 { 6 for(;x<=n;x+=x&(-x)) c[x]+=y; 7 } 8 9 int query(int x) 10 { 11 int res=0; 12 for(;x;x-=x&(-x)) res+=c[x]; 13 return res; 14 } 15 16 int main() 17 { 18 scanf("%d%d",&n,&m); 19 FOR(i,1,n) scanf("%d",&a[i]); 20 while(m--) 21 { 22 int opt;scanf("%d",&opt); 23 if(opt==1) 24 { 25 int x,y,k; 26 scanf("%d%d%d",&x,&y,&k); 27 modify(x,k); 28 modify(y+1,-k); 29 } 30 else 31 { 32 int x;scanf("%d",&x); 33 printf("%d ",query(x)+a[x]); 34 } 35 } 36 return 0; 37 }
线段树(区间修改,区间求值)
const int N=100005; struct tree { int l,r; ll sum,add; #define l(x) t[x].l #define r(x) t[x].r #define sum(x) t[x].sum #define add(x) t[x].add }t[N<<2]; int a[N],n,m; void build(int p,int l,int r) { l(p)=l,r(p)=r; if(l==r) {sum(p)=a[l];return;} int mid=(l+r)>>1,q=p<<1; build(q,l,mid),build(q|1,mid+1,r); sum(p)=sum(q)+sum(q|1); } void pushdown(int p) { if(!add(p)) return; int q=p<<1; sum(q)+=add(p)*(r(q)-l(q)+1); sum(q|1)+=add(p)*(r(q|1)-l(q|1)+1); add(q)+=add(p); add(q|1)+=add(p); add(p)=0; } void modify(int p,int l,int r,int k) { if(l<=l(p)&&r>=r(p)) { sum(p)+=(ll)k*(r(p)-l(p)+1); add(p)+=k; return; } pushdown(p); int mid=(l(p)+r(p))>>1,q=p<<1; if(l<=mid) modify(q,l,r,k); if(r>mid) modify(q|1,l,r,k); sum(p)=sum(q)+sum(q|1); } ll query(int p,int l,int r) { if(l<=l(p) && r>=r(p)) return sum(p); pushdown(p); int mid=(l(p)+r(p))>>1,q=p<<1; ll val=0; if(l<=mid) val+=query(q,l,r); if(r>mid) val+=query(q|1,l,r); return val; } int main() { freopen("hh.out","w",stdout); scanf("%d%d",&n,&m); FOR(i,1,n) scanf("%d",&a[i]); build(1,1,n); while(m--) { int opt;scanf("%d",&opt); if(opt==1) { int x,y,k; scanf("%d%d%d",&x,&y,&k); modify(1,x,y,k); } else { int x,y; scanf("%d%d",&x,&y); printf("%lld ",query(1,x,y)); } } return 0; }
动态开点(权值线段树)
1 struct tree 2 { 3 int lc,rc; 4 int dat; 5 }t[N<<1]; 6 int root,tot; 7 8 int build() 9 { 10 t[++tot].lc=t[tot].rc=t[tot].dat=0; 11 return tot; 12 } 13 void insert(int p,int l,int r,int val,int k) 14 { 15 if(l==r){t[p].dat+=k;return;} 16 int mid=(l+r)>>1; 17 if(val<=mid) 18 { 19 if(!t[p].lc) t[p].lc=build(); 20 insert(t[p].lc,l,mid,val,k); 21 } 22 else 23 { 24 if(!t[p].rc) t[p].rc=build(); 25 insert(t[p].rc,mid+1,r,val,k); 26 } 27 t[p].dat=t[t[p].lc].dat+t[t[p].rc].val; 28 } 29 30 int main() 31 { 32 root=build(); 33 insert(root,1,n,val,k); 34 }
线段树合并(相同权值)
1 int merge(int p,int q,int l,int r) 2 { 3 if(!p) return q; 4 if(!q) return p; 5 if(l==r) {t[p].dat+=t[q].dat;return p;} 6 int mid=(l+r)>>1; 7 t[p].lc=merge(t[p].lc,t[q].lc,l,mid); 8 t[p].rc=merge(t[p].rc,t[q].rc,mid+1,r); 9 t[p].dat=t[t[p].lc].dat+t[t[p].rc].dat; 10 return p; 11 }