线段树

线段树  ——解决区间类问题的利器! 
线段树其实是一棵“二叉树”,其形状跟一般的二叉树没有区别。只 是在这样一棵二叉树中,每个结点记彔的是一段区间的信息。 

父亲:[l,r] 左儿子:[l,(l+r)/2] 右儿子:[(l+r)/2+1,r] 那么怎么存储这样一棵线段树呢

定义如下结构体: 

struct node {  
    int left,right;  //该结点表示区间 的左右端点位置 
    int max,sum;     //记彔这个区间的 相关信息,可以 视情况增删 
};
于是,只需要开一个一维数组就可以了!tree[k]这一 点的左儿子就是tree[k*2],右儿子就是tree[k*2+1]。 


Step 1:建树——初始化线段树,并将原始已知的数据写 入到线段树中。 

void build(int l,int r,int k) {  
    tree[k].left=l;
    tree[k].right=r;  
    if (l==r) {
        tree[k].sum=a[l];
        return;}  
    else  {   
        int mid=(l+r)/2;   
        build(l,mid,k*2);   
        build(mid+1,r,k*2+1);   
        tree[k].sum=tree[k*2].sum+tree[k*2+1].sum;  
    } 
}       

 其中,l,r表示当前要建的子树的根节点所表示区间 的左右端点;k表示这个节点在一维数组中的下标。主函 数中直接调用build(1,N,1)即可完成整个建树过程~ 


Step 2:更新——对于每一个操作1,维护线段树使得每个 结点所表示的区间信息仍然正确。

void update(int pos,int val,int k){  
    if (tree[k].left==tree[k].right){   
        tree[k].sum+=val;
        return;  
    }  
    else{   
        int mid=(tree[k].left+tree[k].right)/2;   
        if (pos<=mid) 
            update(pos,val,k*2);   
        else update(pos,val,k*2+1);   
        tree[k].sum=tree[k*2].sum+tree[k*2+1].sum;  
    } 
}

 对于每个操作1,直接调用update(pos,val,k)就可以了, 其中pos为要更新元素在数列中的下标。 


Step 3:查询——对于每一个操作2,求出所要求区间的元 素之和。 

int query(int l,int r,int k){  
    if (tree[k].left==l && tree[k].right==r)   
        return tree[k].sum;  
    else{   
        int mid=(tree[k].left+tree[k].right)/2;   
        if (l>mid) return query(l,r,k*2+1);   
        else if (r<=mid) return query(l,r,k*2);   
        return query(l,mid,k*2)+query(mid+1,r,k*2+1);  
    } 
} 


总结 
1、线段树可以求解各种有关区间的问题,它的功能很强大。

2、空间复杂度~O(N*4),每次更新戒查询操作的复杂度都是O(logN)。

3、在更新和查询区间[l,r]的时候,为了保证复杂度是严格的O(logN)必须在达到被[l,r]覆盖的区间的结点时就立即返回。而为了保证这样做的正确性,需要在这两个过程中做一些相关的“懒”操作。有了“懒”操作就使得线段树这种结构千变万化~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值