线段树的概念
线段树是一种二叉搜索树,线段树的每个节点存了一个区间,所以得名。线段树如果是非叶子节点一定有两个子节点,如果有左子树那么就一定有右子树。
主要应用是区间最大值以及区间最小值以及区间求和,区间更新。
线段树的数据域
一般存储区间的和,以及区间的最大值,最小值等等。
线段树的操作
以区间求值为例子
struct Node
{
int begin,end;
Node *left;
Node *right;
int sum;
Node(int a,int b,int s):begin(a),end(b),sum(s){}
}
//构造树
Node * buildTree(vector<int>&nums,int begin ,int end )
{
Node *root=NULL;
if(begin==end)
{
root=new Node(begin,end,nums[begin]);
return root;
}
Node* l=buildTree(nums,begin,begin+(end-begin)/2);
Node* r=buildTree(nums,begin+(end-begin)/2+1,end);
root=new Node(begin,end,l->sum+r->sum);
root->left=l;
root->right=r;
return root;
}
//查询树
int queryTree(int i,int j,Node * root)
{
if(root==NULL)
return 0;
if(root->begin<=i&&root->end<=j)
return root->sum;
int mid=root->begin+(root->end-root->begin)/2;
int lsum=0;
int rsum=0;
if(i<=mid)
lsum=query(i,j,root->left);
if(j>mid)
rsum=query(i,j,root->right);
return lsum+rsum;
}
int updateTree(int i,int val,Node * root)
{
int diff=0;
if(root->begin==i&&root->end==i)
{
diff=val-root->sum;
root->sum=val;
}
int mid=root->begin+(root->end-root->begin)/2;
if(i<=mid)
diff=updateTree(i,val,root->left);
if(i>mid)
diff=updateTree(i,val,root->right);
root->sum+=diff;
return diff;
}