郭炜老师的代码 写了下注释 线段树的经典题目
#include<bits/stdc++.h>
using namespace std;
struct CNode
{
int L,R;
CNode * pLeft, * pRight;
long long nSum;//和
long long Inc;//区间累加量
};
CNode Tree[200010];
int nCount = 0;//充当一个指针作用,管理内存
int Mid( CNode * pRoot)
{
return (pRoot->L + pRoot->R)/2;//返回区间中间值
}
void BuildTree(CNode * pRoot,int L, int R)//建树
{
pRoot->L = L;
pRoot->R = R;
pRoot->nSum = 0;
pRoot->Inc = 0;
if( L == R)//叶节点返回
return;
nCount ++;
pRoot->pLeft = Tree + nCount;
nCount ++;
pRoot->pRight = Tree + nCount;
BuildTree(pRoot->pLeft,L,(L+R)/2);
BuildTree(pRoot->pRight,(L+R)/2+1,R);
}
void Insert( CNode * pRoot,int i, int v)//插入值 第i个 值为V
{
if( pRoot->L == i && pRoot->R == i)//如果为叶子节点直接加上累加量结束
{
pRoot->nSum = v;
return ;
}
pRoot->nSum += v;//非叶子节点,在该区间加上累加量继续向下一层更新
if( i <= Mid(pRoot))//小于中间的区间
Insert(pRoot->pLeft,i,v);
else//大于中间的区间
Insert(pRoot->pRight,i,v);
}
void Add( CNode * pRoot, int a, int b, long long c)
{
if( pRoot->L == a && pRoot->R == b)//区间和目标区间相同,直接加到区间的增加量上就行
{
pRoot->Inc += c;
return ;
}
pRoot->nSum += c * ( b - a + 1) ;//如果不相同 把值加到总增加量上后继续向下一层进行
if( b <= (pRoot->L + pRoot->R)/2)//如果[a,b]完全在中间左边则向左递归
Add(pRoot->pLeft,a,b,c);
else if( a >= (pRoot->L + pRoot->R)/2 +1)//同理
Add(pRoot->pRight,a,b,c);
else//跨过两边,同理
{
Add(pRoot->pLeft,a,(pRoot->L + pRoot->R)/2,c);
Add(pRoot->pRight,(pRoot->L + pRoot->R)/2 + 1,b,c);
}
}
long long QuerynSum( CNode * pRoot, int a, int b)
{
if( pRoot->L == a && pRoot->R == b)
return pRoot->nSum +(pRoot->R - pRoot->L + 1) * pRoot->Inc ;//如果到达查询的目标区间 直接返回累计值加上区间每一个元素的增加值的和,就是答案
pRoot->nSum += (pRoot->R - pRoot->L + 1) * pRoot->Inc ;//把区间值加到累计值上往下面带
Add( pRoot->pLeft,pRoot->L,Mid(pRoot),pRoot->Inc);//
Add( pRoot->pRight,Mid(pRoot) + 1,pRoot->R,pRoot->Inc);
pRoot->Inc = 0;//往下带完之后记得归零
if( b <= Mid(pRoot)) //和上面ADD同理 查绚区间分布不同的三种情况
return QuerynSum(pRoot->pLeft,a,b);
else if( a >= Mid(pRoot) + 1)
return QuerynSum(pRoot->pRight,a,b);
else
{
return QuerynSum(pRoot->pLeft,a,Mid(pRoot)) + QuerynSum(pRoot->pRight,Mid(pRoot) + 1,b);
}
}
int main()
{
int n,q,a,b,c;
string cmd;
while(scanf("%d%d",&n,&q)==2){
nCount = 0;
BuildTree(Tree,1,n);
for(int i = 1; i <= n; i ++ )
{
scanf("%d",&a);
Insert(Tree,i,a);
}
for( int i = 0; i < q; i ++ )
{
cin>>cmd;
if ( cmd[0] == 'C' )
{
scanf("%d%d%d",&a,&b,&c);
Add(Tree,a,b,c);
}
else
{
scanf("%d%d",&a,&b);
printf("%lld\n",QuerynSum(Tree,a,b));
}
}
}
return 0;
}