pku3468(线段树)
基础的线段树区间修改和区间求和
贴代码吧
#include <stdio.h> #define N 100010 struct Node { int l,r; __int64 c,sum;//用c来存储在这个节点存储的增值,用sum来存储在该节点对应的区间上的和。 }p[3*N]; int que[N]; void build(int k,int s,int t) { int kl,kr,mid; p[k].l=s;p[k].r=t;p[k].c=0; p[k].sum=que[s]; if(s==t) return ; mid=(s+t)>>1;kl=k<<1;kr=kl+1; build(kl,s,mid); build(kr,mid+1,t); p[k].sum=p[kl].sum+p[kr].sum; } //关键操作,传递时,把之前根节点更新的增值加到子节点,同时把子节点上的sum也更新了 //然后把根节点的值设置为0,以免重复加到子节点 void trans(int k,int lk,int rk) { p[lk].c+=p[k].c; p[rk].c+=p[k].c; p[lk].sum+=p[k].c*(p[lk].r-p[lk].l+1); p[rk].sum+=p[k].c*(p[rk].r-p[rk].l+1); p[k].c=0; } void insert(int k,int s,int t,int v) { if(s<=p[k].l&&t>=p[k].r) { p[k].c+=v; p[k].sum+=v*(p[k].r-p[k].l+1); } else { int mid=(p[k].r+p[k].l)>>1,kl=k<<1,kr=kl+1; if(p[k].c!=0) trans(k,kl,kr); if(s<=mid) insert(kl,s,t,v); if(t>mid) insert(kr,s,t,v); p[k].sum=p[kr].sum+p[kl].sum; } } __int64 query(int k,int s,int t) { if(s<=p[k].l&&t>=p[k].r) return p[k].sum; int mid=(p[k].r+p[k].l)>>1,kl=k<<1,kr=kl+1; if(p[k].c!=0) trans(k,kl,kr); __int64 a=0,b=0; if(s<=mid) a=query(kl,s,t); if(t>mid) b=query(kr,s,t); return a+b; } int main() { char ch; int i,n,m,a,b,t; while(scanf("%d %d",&n,&m)!=EOF) { for(i=1;i<=n;++i) scanf("%d",que+i); build(1,1,n); while(m--) { getchar(); scanf("%c",&ch); if(ch=='Q') { scanf("%d %d",&a,&b); printf("%I64d\n",query(1,a,b)); } else { scanf("%d %d %d",&a,&b,&t); insert(1,a,b,t); } } } return 0; }