线段树讲解+模板(较全)

部分转载:http://blog.csdn.net/metalseed/article/details/8039326
这里写图片描述

图画的太丑了,不忍直视~~~~哎

//tree[]用来表示每个区间的最小值,sum[]区间和,col[]打标记,表明该区间每个元素增加了多少 

//懒标记用在update上,意思是可以不用都更新,用到的时候再更新 
void build(int node,int begin,int end)
{
    if(begin==end)
    {
        tree[node]=array[begin];
        sum[node]=array[begin];
        return;
    }
    int mid=begin+(end-begin)
    build(2*node,begin,mid);
    build(2*node+1,mid+1,end);
    //用tree记录每个区间的最值 
    if(tree[node*2]<=tree[node*2+1])
        tree[node]=tree[2*node];
    else 
        tree[node]=tree[2*node+1];
}
//区间查询 
int query1(int node,int begin,int end,int left,int right)//查询3-5之间的最小值 
{
    int p1,p2;

    if(left>end || right<begin)
        return -1;
    if(begin>=right && end<=right)
        return tree[node];

    int mid=begin+(end-begin)/2;
    p1=query(2*node,begin,mid);
    p2=query(2*node+1,mid+1,end);

    if(p1==-1)return p2;
    if(p2==-1)return p1;
    if(p1<=p2)return p1;
    else return p2; 
}
//单点更新
void updata(int node ,int begin,int end,int ind,int add)//将哪个点ind更新了 add
{
    if(begin==end)
        tree[node]+=add;
    int mid=begin+(end-begin)/2;
    if(ind<=m)
        updata(node*2,left,mid,ind,add);
    else
        updata(node*2+1,mid+1,right,ind,add);
    tree[node]=min(tree[node*2,node*2+1]);
} 

//下放标记 
void pushdown(int rt,int m)
{
    if(col[rt])
    {
        col[rt<<1]=col[rt];
        col[rt<<1|1]=col[rt];
        sum[rt<<1]=col[rt]*(m-m/2);//这个区间要稍微大一点 
        sum[rt<<1|1]=col[rt]*(m/2);
        col[rt]=0; 
    }
} 
//区间修改 
//以修改区间的值并求整个数组的和为例 
void change(int node,int begin,int end,int left,int right,int c)
{
    if(left<=begin && end >=right)
    {
        col[node]=c;//在该节点上打一个标记 标记打给谁了,就一个么? 
        sum[node]=c*(end-begin+1); //做和的时候用了,但是查询的时候不是这个区间了,这时就用到标记下放 
        return;
    }
    pushdown(node,end-begin+1);
    int mid=begin+(end-begin)/2;
    if(left<=mid) change(node*2,begin,end,left,mid,c) ;
    if(right>mid) change(node*2+1,begin,end,mid+1,right,c);
    sum[node]=sum[node*2]+sum[node*2+1];
}

//查询区间之和 
int query2(int node,int begin,int end,int left,int right)
{
    if(left<=begin && end>=right)//不需要就不下放了 
    {
        return sum[node];
    }
    Pushdown(node,end-begin+1);//需要的时候再下放 
    int ret=0;
    int mid=begin+(end-begin)/2;
    if(left<mid) ret+=query2(node*2,begin,end,left,mid,c) ;
    if(right>mid) ret+=query2(node*2+1,begin,end,mid+1,right,c);
    return ret; 
} 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值