poj3468 A Simple Problem with Integers

区间求和,区间更新。

需要覆盖区间,延迟处理。


void PushSub(int rt,int m){
	if(color[rt]){
		color[rt<<1]+=color[rt];
		color[rt<<1|1]+= color[rt];
		sum[rt<<1]+=color[rt]*(m-(m>>1));
		sum[rt<<1|1]+=color[rt]*(m>>1);
		color[rt]=0;
	}
}

这段刚开始怎么都没搞明白。为什么sum[rt<<1] = c*(m-m>>1) ,而sum[rt<<1|1] = c*(m>>1)  。后来仔细想了一下 ,举个例子[4,8] 这个区间的,二分出来变成[4,6],[7,8]

mid= (4 +8)>>1 = 6 ;左子树的区间是[4,mid].右子树是[mid+1,8],所以这样算起来,如果区间有奇数个,左边肯定要比右边大一个。。。瞬间明白。。。


全部代码:

#include<cstdio>
#define M 100005
#define mid ( l+r )>>1
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
__int64 color[M<<2],sum[M<<2];
void PushPlus(int rt){
	sum[rt] = sum[rt<<1] + sum[rt<<1|1]; 
}
void PushSub(int rt,int m){
	if(color[rt]){
		color[rt<<1]+=color[rt];
		color[rt<<1|1]+= color[rt];
		sum[rt<<1]+=color[rt]*(m-(m>>1));
		sum[rt<<1|1]+=color[rt]*(m>>1);
		color[rt]=0;
	}
}
void Bulid(int l,int r,int rt){
	color[l]=0;
	if(l == r){
		scanf("%I64d",&sum[rt]);
		return ;
	}
	int m= mid;
	Bulid(lson);
	Bulid(rson);
	PushPlus(rt);
}
__int64 Query(int L,int R,int l,int r,int rt){
	if(L<=l && r<=R){
		return sum[rt];
	}
	PushSub(rt,r-l+1);
	int m=mid;
	__int64 ans=0;
	if(L<=m)
		ans+=Query(L,R,lson);
	if(R>m)
		ans+=Query(L,R,rson);
	return ans;

}
void Change(__int64 x,int L,int R,int l,int r,int rt){

	if(L<=l && r<=R){
		sum[rt]+=((r-l+1)*x);
		color[rt]+=x;
		return ;
	}
	PushSub(rt,r-l+1);
	int m = mid;
	if(L<=m)
		Change(x,L,R,lson);
	if(R>m)
		Change(x,L,R,rson);
	PushPlus(rt);
}
int main(){
	int n,m,a,b;
	__int64 c;
	char op[2];
	while(~scanf("%d %d",&n,&m)){
		Bulid(1,n,1);
		while(m--){
			scanf("%s",op);
			if(op[0] == 'Q'){
				scanf("%d %d",&a,&b);
				printf("%I64d\n",Query(a,b,1,n,1));
			}
			else{
				scanf("%d %d %I64d",&a,&b,&c);
				Change(c,a,b,1,n,1);
			}
		}
	}
	return 0;
}


你可能感兴趣的:(poj3468 A Simple Problem with Integers)