线段树进阶之递归实现
——————————————————————————浅喜如苍狗,深爱如长风。
以下以维护数列区间和的线段树为例,演示最基本的线段树代码。
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 }