一.线段树的引入
做题的时候遇到了BMQ问题,就是求给定区间中的最大值最小值问题,暴力搜索只限于数据范围较小,控制在1000-10000左右的时候。而线段树解决了O(nlogn)的时间复杂度,其中建树为O(n).
二.线段树的性质
1.平衡二叉树,最大深度为logn
2.树中每一个节点代表一个区间(叶子节点是一个点)
3.每个节点完全包含他的所有子孙节点
4.任意两个节点要么是完全包含,要么互不相交
5.在进行区间操作和统计时把区间等价转换为若干个子区间的相同操作
三.区间和例子
#include<iostream>
using namespace std;
#define Maxn 1100
int tree[4*Maxn];
int a[Maxn];
void build(int p,int l,int r) //建树
{
if(l==r)
{
tree[p]=a[l];//a[r]也可以
return ;
}
int mid=(l+r)/2;
build(2*p,l,mid);
build(2*p+1,mid+1,r);
tree[p]=tree[2*p]+tree[2*p+1];//这一句可以根据题面发生改变,这里是区间和。
}
void change(int p,int l,int r,int x,int num) //修改a数组里x节点,修改为num
{
if(l==r)
{
tree[p]=num;
return ;
}
int mid=(l+r)/2;
else if(x<=mid) change(2*p,l,mid,x,num);
else change(2*p+1,mid+1,r,x,num);
tree[p]=tree[2*p]+tree[2*p+1];//返回的时候递归修改
}
int find(int p,int l,int r,int x,int y)
{
if(x<=l&&r<=y) return tree[p];
int mid=(l+r)/2;
if(y<=mid) return find(2*p,l,mid,x,y);
if(x>mid) return find(2*p+1,mid+1,r,x,y);
return find(2*p,l,mid,x,mid)+find(2*p+1,mid+1,r,mid+1,y);
}
四. 线段树关键
需要维护哪些区间信息,怎样去维护这个信息