线段树模板

线段树模板

//建树
void built(int root,int left,int right)
{
    tree[root].lazy=0;//lazy标志初始化为0
    /*记录节点对应的区间
    tree[root].left=left;
    tree[root].right=right;
    */
    if(left==right)//递归出口
    {
        tree[root]=num[left];
        return ;
    }
    int mid=(left+right)/2;
    built(root*2+1,left,mid);//这里线段树根节点从0开始,若从1开始,左右子树的根节点的index要减1
    built(root*2+2,mid+1,right);
    tree[root].value=tree[root*2+1].value+tree[root*2+2].value;//以sum为value的线段树
    tree[root].value=min(tree[root*2+1].value,tree[root*2+2].value);//以最小值为value的线段树
    tree[root].value=max(tree[root*2+1].value,tree[root*2+1].value);//以最大值为value的线段树
}

//sum类型树查询
//如果每个树节点都记录了left和right值,则这里的start与end参数可以不需要(其他函数同理)
int query(int root,int start,int end,int left,int right)
{
    if(start==end) return tree[root].value;
    else if(start>right || end<left) //没有交集
        return 0;
    else if(start>=left && right>=end) //区间包含
        return tree[root].value;
    else
    {
        int mid=(start+end)/2;//如果没有start和end参数 (tree[root].left+tree[root].right)/2
        return query(root*2+1,start,mid,left,right)+query(root*2+2,mid+1,end,left,right);
    }
}

//sum类型树单点更新
void update(int root,int start,int end,int index,int value) //根据index改value
{
    if(start==end)
    {
        num[index]=value;
        tree[root].value=value;
        return ;
    }
    int mid=(start+end)/2;
    if(index<=mid) update(root*2+1,start,mid,index,value);
    else update(root*2+2,mid+1,end,index,value);
    tree[root].value=tree[root*2+1].value+tree[root*2+2].value;
}

void pushdown(int root)//标记下传
{
    if(tree[root].lazy)
    {
        tree[root*2+1].lazy+=tree[root].lazy;
        tree[root*2+1].val+=tree[root].lazy;
        tree[root*2+2].lazy+=tree[root].lazy;
        tree[root*2+2].val+=tree[root].lazy;
        tree[root].lazy=0;
    }
}

//min 或 max 类型树 查询(min和max大体框架差不多但是具体细节有差别)
int query(int root,int start,int end,int left,int right)
{
    if(start>right || end<left) //没有交集
        return ;
    else if(left>=start && right<=end)//包含在区间内
        return tree[root].val;
    int mid=(start+end)/2;
    if(tree[root].lazy) pushdown(root);
    if(right<=mid) return query(root*2+1,start,mid,left,right);
    else if(left>mid) return query(root*2+2,mid+1,end,left,right);
    else   return min(query(root*2+1,start,mid,left,right),query(root*2+2,mid+1,end,left,right));
}

//min类型树 区间更新
void update(int root,int start,int end,int left,int right,int value)
{
    if(start>=left && end<=right)
    {
        tree[root].value+=value;
        tree[root].lazy+=value;
        return ;
    }
    if(tree[root].lazy) pushdown(root);
    int mid=(start+left)/2;
    if(mid>=right) update(root*2+1,start,mid,left,right);
    else if(left>mid) update(root*2+2,mid+1,end,left,right);
    else
    {
        update(root*2+1,start,mid,left,right);
        update(root*2+2,mid+1,end,left,right);
    }
    tree[root].value=min(tree[root*2+1].value,tree[root*2+2].value);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值