http://acm.hust.edu.cn:8080/judge/problem/viewProblem.action?id=14607
题意:题目给你n个数,m个操作,接下来一行给你这n个数,接下的几行给出m个操作,Q a b 表示查询区间[a,b]里的数和和。U a b c 表示把区间[a,b]里的数都加上c。
思路:延迟标记,和hdu4107是同一种类型的,这是4107的解题过程http://www.cnblogs.com/ziyi--caolu/archive/2012/12/25/2832368.html
反思:在解题过程中,有些地方没有思考清楚,费了好多时间。比如再往下更新的时候,要和与要加的数一起更新,一开始,我是想成,只更新add,在最后求和的时候,再将add加上,结果这样是错的........
#include<iostream>
using namespace std;
#define N 100005
typedef __int64 ss;
struct
{int l,r;ss sum,add;
}tree[N*4];
ss a[N];
void creat(int i,int l,int r)
{int mid=(l+r)/2;tree[i].l=l;tree[i].r=r;tree[i].sum=tree[i].add=0;if(l==r){tree[i].sum=a[l];return ;}creat(i*2,l,mid);creat(i*2+1,mid+1,r);tree[i].sum=tree[i*2].sum+tree[i*2+1].sum;
}
void updata(int i,int l,int r,int c)
{if(l<=tree[i].l&&tree[i].r<=r){tree[i].add+=c;tree[i].sum+=c*(tree[i].r-tree[i].l+1);return;}if(tree[i].add!=0){tree[i*2].add+=tree[i].add;tree[i*2+1].add+=tree[i].add;tree[i*2].sum+=tree[i].add*(tree[i*2].r-tree[i*2].l+1);tree[i*2+1].sum+=tree[i].add*(tree[i*2+1].r-tree[i*2+1].l+1);tree[i].add=0;}int mid=(tree[i].l+tree[i].r)/2;if(mid>=l)updata(i*2,l,r,c);if(mid<r)updata(i*2+1,l,r,c);tree[i].sum=tree[i*2].sum+tree[i*2+1].sum;
}
ss getsum(int i,int l,int r)
{if(tree[i].l>=l&&tree[i].r<=r){return tree[i].sum;}if(tree[i].add!=0){tree[i*2].add+=tree[i].add;tree[i*2+1].add+=tree[i].add;tree[i*2].sum+=tree[i].add*(tree[i*2].r-tree[i*2].l+1);tree[i*2+1].sum+=tree[i].add*(tree[i*2+1].r-tree[i*2+1].l+1);tree[i].add=0;}int mid=(tree[i].l+tree[i].r)/2;ss sum1=0,sum2=0;if(mid>=l)sum1=getsum(i*2,l,r);if(mid<r)sum2=getsum(i*2+1,l,r);return sum1+sum2;
}
int main()
{int n,q;while(scanf("%d %d",&n,&q)>0){int i;for(i=1;i<=n;i++)scanf("%I64d",&a[i]);creat(1,1,n);while(q--){char t[10];scanf("%s",t);if(t[0]=='Q'){int l,r;scanf("%d%d",&l,&r);printf("%I64d\n",getsum(1,l,r));}else{int l,r,c;scanf("%d%d%d",&l,&r,&c);updata(1,l,r,c);}}}return 0;
}