poj A Simple Problem with Integers(線段樹,成端更行)

延遲標記(或者說懶惰標記),就是每次更新的時候不要更新到底,用延遲標記使得更新延遲到下次需要更新or詢問到的時候。

#include <stdio.h>
#define maxn 100050
#define lson l , m , rt * 2
#define rson m+1 , r ,rt *2 +1
#define dem  m = (l + r) / 2

__int64 sum[maxn*4];
__int64 col[maxn*4];
void PushUp(__int64 rt){
	sum[rt] = sum[rt*2] + sum[rt*2+1];
}
void PushDown(__int64 rt,__int64 m)
{
	if(col[rt]!=0)
	{
		col[rt*2] +=  col[rt];      //用+= 而非 = ,這樣就避免了所加值得覆蓋 
		col[rt*2+1] += col[rt];    
		sum[rt*2] += (m-m/2) * col[rt]; // 左孩子區間大,m表示的是父親節點的區間大小,而非(l+r)
		sum[rt*2+1] += (m/2) * col[rt];
		col[rt] = 0;	
	}	
}
void build(__int64 l,__int64 r,__int64 rt){
	col[rt] = 0;
	if(l == r){
		scanf("%I64d",&sum[rt]);
		return ;
	}
	__int64 dem;
	build(lson);
	build(rson);
	PushUp(rt);
}
void update(__int64 L,__int64 R,__int64 add,__int64 l,__int64 r,__int64 rt){
	if(L <= l && r <= R){
		col[rt] += add;
		sum[rt] += (r - l + 1)*add;
		return ;
	}
	PushDown(rt,r-l+1);
	__int64 dem;
	if(L <= m) update(L,R,add,lson);
	if(R > m)  update(L,R,add,rson);
	PushUp(rt);
}
__int64 query(__int64 L,__int64 R,__int64 l,__int64 r,__int64 rt)
{
	if(L <=l && r <= R)
	{
		return sum[rt];	
	}	
	PushDown(rt,r-l+1);         //查詢時,遇到延時標記,也要將所加值向下更新至孩子節點。
	__int64 dem;
	__int64 res = 0;
	if(L <= m) res += query(L,R,lson);
	if(R > m)  res += query(L,R,rson);
	return res;
}
int main()
{
	//freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
	__int64 n,T;
	char str[3];
	__int64 a,b,c;
	while(scanf("%I64d%I64d",&n,&T)==2)
	{
		build(1,n,1);
		while(T--)
		{
			scanf("%s",str);
			if(str[0]=='Q')	{
				scanf("%I64d%I64d",&a,&b);
				printf("%I64d\n",query(a,b,1,n,1));
			}
			else{
				scanf("%I64d%I64d%I64d",&a,&b,&c);
				update(a,b,c,1,n,1);
				//for(int j=1;j<=10*3;j++)
				//	printf("%d ",sum[j]);
			}
		}	
	}	
	return 1;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章