http://poj.org/problem?id=3468
题目大意:
给你n个整数,两种操作,
求一段区间的和
一段区间内全部加上某个整数
简单线段树题
区间内一部分是固定区间和
另一个是此区间内每个数都需要加的量
注意用64为整数
详情见代码注释:
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<queue> #include<algorithm> using namespace std; const int N=100005; struct node { int l,r; long long add;//非固定,需要向下传递的量 long long v;//固定住的和 }mem[N*4]; int a[N]; long long ans; void build(int x,int l,int r) { mem[x].l=l; mem[x].r=r; mem[x].add=0;//初始化 if(l==r) { mem[x].v=a[l]; } else { int mid=(l+r)>>1; build(x*2,l,mid); build(x*2+1,mid+1,r); mem[x].v=mem[x*2].v+mem[x*2+1].v; } } void findsum(int x,int i,int j) { if(mem[x].l==i&&mem[x].r==j) { ans=ans+mem[x].v+(mem[x].r-mem[x].l+1)*mem[x].add;//如果正好是这个区间 } else { int mid=(mem[x].l+mem[x].r)>>1; mem[x].v+=(mem[x].r-mem[x].l+1)*mem[x].add;//否则向下传递,首先本区间固定量增加 mem[x*2].add+=mem[x].add;mem[x*2+1].add+=mem[x].add;//然后传给左右区间 mem[x].add=0;//最后清零 if(j<=mid) { findsum(x*2,i,j); }else if(i>mid) { findsum(x*2+1,i,j); }else { findsum(x*2,i,mid); findsum(x*2+1,mid+1,j); } } } void Addint(int x,int i,int j,int k) { if(mem[x].l==i&&mem[x].r==j) { mem[x].add+=k;//本区间改变增加量 } else { mem[x].v+=(j-i+1)*k;//向下的话,首先本区间先将固定量增加 int mid=(mem[x].l+mem[x].r)>>1; if(j<=mid) { Addint(x*2,i,j,k); }else if(i>mid) { Addint(x*2+1,i,j,k); }else { Addint(x*2,i,mid,k); Addint(x*2+1,mid+1,j,k); } } } int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF) { for(int i=1;i<=n;++i) { scanf("%d",&a[i]); } build(1,1,n); while(m--) { char c; int i,j,k; getchar();//吃换行 scanf("%c",&c); if(c=='Q') { scanf("%d %d",&i,&j); ans=0; findsum(1,i,j); printf("%I64d\n",ans); } else { scanf("%d %d %d",&i,&j,&k); Addint(1,i,j,k); } } } return 0; }