宝藏知识点链接
线段树:
1,相当于用树的结点表示一个区间,结点值存储与数组中,左右子节点是父节点的二分区间
2,不难发现,线段树的使用中的共性:
- 参数传入左右端点,代表当前结点所表示的区间
- 参数传入当前位置pos,代表当前区间的区间和所在val数组中的位置
- 通过二分对左右子树操作(类似于树的操作)
实现代码:
递归创建,相当于后续遍历
#include <iostream>
#include<vector>
using namespace std;
class Segment_tree{
public:
void build_segment_tree(vector<int> &val,vector<int> &nums,int pos,int left,int right){
if(left==right)
{
val[pos]=nums[left];
return ;
}
int mid=(left+right)/2;
build_segment_tree(val,nums,pos*2+1,left,mid);
build_segment_tree(val,nums,pos*2+2,mid+1,right);
val[pos]=val[2*pos+1]+val[2*pos+2];
}
区间求和
int InteravlSum(vector<int> &val,int left,int right,int sleft,int sright,int pos){
if(left<=sleft&&right>=sright)
return val[pos];
int mid=(sleft+sright)/2;
int sum=0;
if(left<=mid)
sum+=InteravlSum(val,left,right,sleft,mid,pos*2+1);
if(right>mid)
sum+=InteravlSum(val,left,right,mid+1,sright,pos*2+2);
return sum;
}
更新
void update_segment_tree(vector<int> &val,int index,int newVal,int sleft,int sright,int pos){
if(sleft==sright&&sleft==index){
val[pos]=newVal;
return;
}
int mid=(sleft+sright)>>2;
if(index<=mid)
update_segment_tree(val,index,newVal,sleft,mid,pos*2+1);
else
update_segment_tree(val,index,newVal,sleft,mid,pos*2+2);
val[pos]=val[pos*2+1]+val[pos*2+2];
}
};
测试
int main()
{
int n;
cin>>n;
vector<int> val(4*n);
vector<int> nums(n);
for(int i=0;i<n;i++)
{
int k;
cin>>k;
nums[i]=k;
}
Segment_tree().build_segment_tree(val,nums,0,0,n-1);
cout<<Segment_tree().InteravlSum(val,0,n-1,0,n-1,0);
Segment_tree().update_segment_tree(val,0,2,0,n-1,0);
cout<<Segment_tree().InteravlSum(val,0,5,0,n-1,0);
}