线段树进阶之递归实现

——————————————————————————浅喜如苍狗,深爱如长风。

以下以维护数列区间和的线段树为例,演示最基本的线段树代码。

1.定义:

1 #define maxn=100007
2 int Sum[maxn<<2],Add[maxn<<2];
3 int A[maxn],n;

2.建树:

void Pushup(int rt){Sum[rt]=Sum[rt<<1]+Sum[rt<<1|1];}
void Build(int l,int r,int rt)
{
	if(l==r){
		Sum[rt]=A[l];
		return;
	}
	int m=(l+r)>>1;
	Build(l,m,rt<<1);
	Build(m+1,r,rt<<1|1);
	Pushup(rt);
} 

3.点修改:

假设A[L]+=C:

//点修改
//假设A[L]+=C:
void Update(int L,int C,int l,int r,int rt)
{
	if(l==r)
	{
		Sum[rt]+=C;
		return;
	}
	int m=(l+r)>>1;
	if(L<=m) Update(L,C,l,m,rt<<1);
	else Update(L,C,m+1,r,rt<<1|1);
	Sum[rt]=Sum[rt<<1]+Sum[rt<<1|1];
}

  

4.区间修改:

 1 //A[L,R]+=C
 2 void Update(int L,int R,int C,int l,int r,int rt)
 3 {
 4     if(L<=l && r<=R)
 5     {
 6         Sum[rt]+=C*(r-l+1);
 7         Add[rt]+=C;//增加Add标记,表示本区间的Sum正确,子区间的Sum仍需要根据Add的值来调整
 8         return;
 9     }
10     int m=(l+r)>>1;
11     PushDown(rt,m-l+1,r-m); //下推标记
12     if(L<=m) Update(L,R,C,l,m,rt<<1);
13     if(R>m) Update(L,R,C,m+1,r,rt<<1|1);
14     PushUp(rt);
15 }

5.区间查询:

 1 void PushDown(int rt,int ln,int rn)
 2 {
 3     if(Add[rt])
 4     {
 5         Add[rt]+=Add[rt];
 6         Add[rt<<1|1]+=Add[rt];
 7         Sum[rt<<1]+=Add[rt]*ln;
 8         Sum[rt<<1|1]++Add[rt]*rn;
 9         Add[rt]=0;
10     }
11 }
 1 int Query(int L,int R,int l,int r,int rt)
 2 {
 3     if(L<=l && r<=R) return Sum[rt];
 4     int m=(l+r)>>1;
 5     PushDown(rt,m-l+1,r-m);
 6     int ANS=0;
 7     if(L<=m) ANS+=Query(L,R,l,m,rt<<1);
 8     if(R>m)  Ans+=Query(L,R,m+1,rt<<1|1);
 9     return ANS;
10 }

猜你喜欢

转载自www.cnblogs.com/dragondragon/p/11253598.html