非再帰版セグメントツリーテンプレート
ここから
(0)定義:
(1)ツリーの作成:
(2)点修正:
(3)点修正下の区間照会:
A[L…R]の和を求めます(点の修正はAddを使っていないので考慮する必要はありません)
コードは非常に簡潔で、理解しにくいわけではありません.
sとtはそれぞれ前の論述の左右の青色ノードを表し,残りのコードは前の論述に基づいて容易に理解できるはずである.
st 1はsとtの父親が同じ時間に0となり,ループを終了する.
2つのifは,sとtがそれぞれ左サブノードであるか右サブノードであるかを判断し,必要に応じてSumを計算する.
(4)区間修正:
(5)区間修正下の区間照会:
A[L…R]の和を求めます
(0)定義:
#define maxn 100007
int A[maxn],n,N;// ,n ,N
int Sum[maxn<<2];//
int Add[maxn<<2];//
(1)ツリーの作成:
void Build(int n){
// N
N=1;while(N < n+2) N <<= 1;
//
for(int i=1;i<=n;++i) Sum[N+i]=A[i];// +N=
//
for(int i=N-1;i>0;--i){
//
Sum[i]=Sum[i<<1]+Sum[i<<1|1];
// Add
Add[i]=0;
}
}
(2)点修正:
A[L]+=C
void Update(int L,int C)
{
for(int s=N+L;s;s>>=1)
Sum[s]+=C;
}
(3)点修正下の区間照会:
A[L…R]の和を求めます(点の修正はAddを使っていないので考慮する必要はありません)
コードは非常に簡潔で、理解しにくいわけではありません.
sとtはそれぞれ前の論述の左右の青色ノードを表し,残りのコードは前の論述に基づいて容易に理解できるはずである.
st 1はsとtの父親が同じ時間に0となり,ループを終了する.
2つのifは,sとtがそれぞれ左サブノードであるか右サブノードであるかを判断し,必要に応じてSumを計算する.
int Query(int L,int R){
int ANS=0;
for(int s=N+L-1,t=N+R+1;s^t^1;s>>=1,t>>=1){
if(~s&1) ANS+=Sum[s^1];
if( t&1) ANS+=Sum[t^1];
}
return ANS;
}
(4)区間修正:
A[L..R]+=C
void Update(int L,int R,int C){
int s,t,Ln=0,Rn=0,x=1;
//Ln: s
//Rn: t
//x:
for(s=N+L-1,t=N+R+1;s^t^1;s>>=1,t>>=1,x<<=1){
// Sum
Sum[s]+=C*Ln;
Sum[t]+=C*Rn;
// Add
if(~s&1) Add[s^1]+=C,Sum[s^1]+=C*x,Ln+=x;
if( t&1) Add[t^1]+=C,Sum[t^1]+=C*x,Rn+=x;
}
// Sum
for(;s;s>>=1,t>>=1){
Sum[s]+=C*Ln;
Sum[t]+=C*Rn;
}
}
(5)区間修正下の区間照会:
A[L…R]の和を求めます
int Query(int L,int R){
int s,t,Ln=0,Rn=0,x=1;
int ANS=0;
for(s=N+L-1,t=N+R+1;s^t^1;s>>=1,t>>=1,x<<=1){
//
if(Add[s]) ANS+=Add[s]*Ln;
if(Add[t]) ANS+=Add[t]*Rn;
//
if(~s&1) ANS+=Sum[s^1],Ln+=x;
if( t&1) ANS+=Sum[t^1],Rn+=x;
}
//
for(;s;s>>=1,t>>=1){
ANS+=Add[s]*Ln;
ANS+=Add[t]*Rn;
}
return ANS;
}