//线段树,节点更新,区间求和
#include <iostream>
using namespace std;
const int MAXN = 50000 + 100; //最大区间
struct treeNode
{
intleft; //左区间
intright; //右区间
intnum; //区间和
}node[MAXN*3]; //节点数大约是最大区间的2倍,但是数组的下标要开到3倍
int num[MAXN];
int buildTree(int low, int top, int index)//功能:建树.父节点是左右子节点之和
{
node[index].left= low;
node[index].right= top;
if(low == top) //是否已经递归到最低层
{
node[index].num = num[low];
return node[index].num;
}
intmid = (low + top) / 2;
//父节点为左右子节点之和
node[index].num= buildTree(low,mid,index*2) + buildTree(mid+1,top,index*2+1); returnnode[index].num;
}
void update(int k, int num, int index) //题目的更新是指节点上加上num
{
node[index].num= node[index].num + num; //每一个覆盖的区间都加上num
if(node[index].left == node[index].right && node[index].left == k) //已经更新到最底层并且找到K点
{
return;
}
intmid = (node[index].left + node[index].right) / 2;
if(k <= mid) //如果k在左子树中
{
update(k,num,index*2);
}
else //如果k在右子树中
{
update(k,num,index*2+1);
}
}
int search(int low, int top, int index)
{
if(node[index].left == low && node[index].right == top) //找到完全重合的区间,直接返回该值,即为本次搜索的最终结果
{
return node[index].num;
}
intmid = (node[index].left + node[index].right) / 2;
if(top <= mid) //搜索区间位于左子树
{
return search(low,top,index*2);
}
elseif(low > mid) //搜索区间位于右子树
{
return search(low,top,index*2+1);
}
else //搜索区间在左右子树间,即将区间分成2部分
{
return search(low,mid,index*2) +search(mid+1,top,index*2+1);
}
}
int main()
{
intn;
cin>>n; //区间[1,n]
for(int i=1; i<=n; i++)
{
cin>>num[i]; //每个点的初始值
}
buildTree(1,n,1); //建树
updata(3,10,1); //3号点增加10
cout<<search(2,4,1); //区间[2,4]的总和
return0;
}
线段树
最新推荐文章于 2020-02-12 11:08:57 发布