题目链接:http://poj.org/problem?id=3468
在HDOJ上有一个名字和这道题一模一样的题,在分类上也都是分到了数据结构里,小编我以为是同一道题,粘了自己HDOJ上的代码,怎么样都是WA,后来才发现题不一样=.=。
题意:给我们n个整数,然后会有m次操作,如果操作是C,输入三个数a,b,c,表示从a到b之间的数加上c,如果操作是Q,输入两个数a,b,输出从a到b之间的所有值的和。
仔细分析,这道题是属于区间更新,区间查询,算是一道基础的线段树题目,对于区间更新,我们采取Lazy的思想,也就是延迟更新的思想。小编这里详细介绍一下。首先我们先来回顾一下线段树的单点更新(如果不会的话,小编建议还是去先看看),在单点更新的时候我们的延伸往往都是直接延伸到了需要更新的那个根节点上,试想如果我们是区间更新的话真的有必要所有的点都更新到所有的根节点,如果我们需要更新的那个区间已经在我们当前搜索的那个区间里面了,我们就可以结束了,当下次需要遍历到再下方的根节点时我们再进行更新,这就是Lazy延迟标记法。
#include<algorithm> #include<cstdio> #include<cstring> #include<iostream> #define MAX 110000 #define LL long long using namespace std; LL n,m; LL ans; struct Tree { LL l,r; LL sum,add; }; Tree tree[MAX*3]; void PushUp(LL rt) { tree[rt].sum = tree[rt<<1].sum+tree[(rt<<1)+1].sum; } void PushDown(LL rt) { LL tmp = rt<<1; tree[tmp].add += tree[rt].add; tree[tmp+1].add += tree[rt].add; tree[tmp].sum += tree[rt].add*(tree[tmp].r-tree[tmp].l+1); tree[tmp+1].sum += tree[rt].add*(tree[tmp+1].r-tree[tmp+1].l+1); tree[rt].add = 0; } void Build(int l,int r,int rt) { tree[rt].l = l; tree[rt].r = r; tree[rt].add = 0; if(l == r) { scanf("%lld",&tree[rt].sum); return ; } int tmp = rt<<1; int mid = (l+r)>>1; Build(l,mid,tmp); Build(mid+1,r,tmp+1); PushUp(rt); //Èç¹ûÔÚ½¨Ê÷µÄ¹ý³ÌÖиøsum¸³Öµ£¬¼ÇµÃºóÃæÒªpushup } void Update(LL l,LL r,LL c,LL rt) { if(r<tree[rt].l || l>tree[rt].r) return ; if(l<=tree[rt].l && r>=tree[rt].r) { tree[rt].add += c; tree[rt].sum += c*(tree[rt].r-tree[rt].l+1); return ; } if(tree[rt].add) PushDown(rt); LL tmp = rt<<1; Update(l,r,c,tmp); Update(l,r,c,tmp+1); PushUp(rt); } void Query(LL l,LL r,LL rt) { if(r<tree[rt].l || l>tree[rt].r) //Òª²éѯµÄÇø¼ä²»ÔÚ¸ÃÇø¼äÉÏ return ; if(l<=tree[rt].l && r>=tree[rt].r) //Òª²éѯÇø¼ä°üÀ¨Á˸ÃÇø¼ä { ans += tree[rt].sum; return ; } if(tree[rt].add) PushDown(rt); LL tmp = rt<<1; LL mid = (tree[rt].l+tree[rt].r)>>1; if(r <= mid) Query(l,r,tmp); else if(l > mid) Query(l,r,tmp+1); else { Query(l,mid,tmp); Query(mid+1,r,tmp+1); } } int main() { while(~scanf("%lld %lld",&n,&m)) { Build(1,n,1); char str[5]; while(m--) { scanf("%s",str); if(str[0]=='Q') { LL l,r; scanf("%lld %lld",&l,&r); ans=0; Query(l,r,1); printf("%lld\n",ans); } else { LL l,r,c; scanf("%lld %lld %lld",&l,&r,&c); Update(l,r,c,1); } } } return 0; }