题目大意:
题目挺好理解的,就是给你一串数字,然后会在某一区间上,使区间的所有数字都加上一个数,也就是更新这段区间的数字,最后再进行对某一区间的求值操作。
题目分析:
因为这道题目和我之前刚刚做的那道题目很类似,都是区间段更新的题目,但是有所不同的是,那个题目是直接赋值更新,而这个题目是区间进行加和,不是直接赋值,所以就有一点比较麻烦的是,是否需要对单个叶子节点进行更新,如果更新,无疑要耗费很多的时间,但是如果不更新,又难以处理数据,得到正确的求解。
后来在网上看到了一个线段树的很好的思想,就是lazy思想,简单来说,就是首先更新父节点,当恰好属于父节点的时候,可以直接得出答案,否则再次向下更新子节点。分别有两个函数,一个是pushup(),是向上更新父节点。一个是pushdown(),是向下更新子节点。
这个lazy思想主要是用在update里的。if(tree[rt].l == l && r == tree[rt].r) 这里就是用到Lazy思想的关键时刻 正如上面说提到的,这里首先更新该节点的sum[rt]值,然后更新该节点具体每个数值应该加多少即add[rt]的值,注意此时整个函数就运行完了,直接return,而不是还继续向子节点继续更新,这里就是Lazy思想,暂时不更新子节点的值。那么什么时候需要更新子节点的值呢?答案是在某部分update操作的时候需要用到那部分没有更新的节点的值的时候,这里可能有点绕口。这时就掉用PushDown()函数更新子节点的数值。
接下来的查询就需要用到rt子节点的值了,由于我们用了Lazy操作,这段的数值还没有更新,因此我们需要调用PushDown函数去更新之,满足if(add[rt])就说明还没有更新。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define LL long long
#define lson l,mid,rt*2
#define rson mid+1,r,rt*2+1
#define maxn 100000+10
LL sum[maxn<<2];
LL add[maxn<<2];
void pushup(int rt){
sum[rt]=sum[rt*2]+sum[rt*2+1];
}
void pushdown(int rt,int m){
if(add[rt]){
add[rt*2]+=add[rt];
add[rt*2|1]+=add[rt];
sum[rt*2]+=add[rt]*(m-m/2);
sum[rt*2|1]+=add[rt]*(m/2);
add[rt]=0;
}
}
void build(int l,int r,int rt){
add[rt]=0;
if(l==r){
scanf("%I64d",&sum[rt]);
return ;
}
int mid=( l + r )/2;
build(lson);
build(rson);
pushup(rt);
}
void update(int L,int R,int c,int l,int r,int rt){
if( L<=l && r<=R ){
add[rt] += c;
sum[rt] += ( r-l +1 )*(LL)c;
return ;
}
pushdown(rt,r-l+1);
int mid = ( l+r ) / 2;
if(L<=mid)
update(L,R,c,lson);
if(R>mid)
update(L,R,c,rson);
pushup(rt);
}
LL query(int L,int R,int l,int r,int rt){
if( L<=l && R>=r )
return sum[rt];
pushdown(rt,r-l+1);
int mid=(l+r)/2;
int rnt=0;
if( L <= mid ) rnt+=query(L,R,lson);
if( R > mid ) rnt+=query(L,R,rson);
return rnt;
}
int main(){
int N,Q,a,b,c;
scanf("%d%d",&N,&Q);
build(1,N,1);
while(Q--){
char s[5];
scanf("%s",s);
if(s[0]=='Q'){
scanf("%d%d",&a,&b);
printf("%I64d\n",query(a,b,1,N,1));
}
if(s[0]=='C'){
scanf("%d%d%d",&a,&b,&c);
update(a,b,c,1,N,1);
}
}
return 0;
}
http://blog.csdn.net/acceptedxukai/article/details/6933446以上的有很多是学习这篇博客的